CodeIQの問題に挑戦してください。

CodeIQにObjective-Cの問題を出題しました。問題は2問あります。
1問目は難易度2(4段階)、2問目は難易度3です。どちらも日付から曜日を求める問題ですが、2問目は実際にはクラス拡張の方法を試す問題です。CodeIQに登録しなくても問題を見ることができるようにしてあります。どちらも6月9日が締めきりです(それ以降は問題を見ることができなります)。

ぜひ、チャレンジしてみてください!

1問目 日付から曜日を求めよう(東京オリンピックの開会式が何曜日なのかを求めます)

2問目 クラス拡張の第3の方法

ただし、正解を知るには登録して解答を提出する必要があります。答えがわからない人ほど正解が知りたいでしょうが、CodeIQはそういうシステムなのでぼくにはなんとも・・・(^^;;

先の投稿でActionScript3とObjective-Cのクラス定義の違いについて比較しましたが、今度はJavaとObjective-Cのクラス定義の違いについて見てみましょう。Javaがわかる人がObjective-Cを学ぶために、逆にObjective-Cはわかったから次はJavaを始めようという人にとっての相互の知識補完になると思います。ActionScript3が得意な人はJavaのシンタックスを見て、「あれ?ActionScript3と似てる!?」と思うかもしれませんね。

では、両者のクラス定義のコードを比較してみます。

Javaのクラス定義
JavaでMyClassを定義するならば、クラス名と同名のMyClass.javaを作り、次のような構造のコードを記述します。
package{
  public class MyClass{

  //コンストラクタ
  MyClass(){
  }

  //インスタンスメソッド
  public void hello(){
    System.out.println("ハロー");
  }
}
Objective-Cのクラス定義
Objective-CでMyClassを定義する場合は、ヘッダファイルのMyClass.hと実装ファイルのMyClass.mの2つのファイルを使います。簡単に言えば、ヘッダファイルには他のクラスからアクセスできるプロパティやメソッドの宣言文を書き、実装ファイルでプロパティの値の設定、メソッドの定義文を書きます。

ヘッダファイル MyClass.h
#import <Foundation/Fundation.h>

@interface MyClass:NSObject
- (void)hello;
@end

実装ファイル MyClass.m
#import "MyClass.h"

@implementation MyClass

- (void)hello{
  NSLog(@"ハロー");
}

@end

Objective-Cにはpackageもコンストラクタもありません。メソッドの前の-は、もちろんマイナスの負号ではありません。-はインスタンスメソッドを示します。+ならばクラスメソッドです。クラス図のUMLでは+ -でメンバーのアクセス権を示しますが、それとは違うので間違えないようにしてください。
では、Objective-Cではどうやってクラスのインスタンスを作るのでしょう?次にインスタンスを作る方法を比較してみます。

Javaでインスタンスを作る
JavaではnewキーワードでMyClassコンストラクタを呼び出すとインスタンスが返ります。
MyClass myObj = new MyClass();
Objective-Cでインスタンスを作る
Objective-Cにはコンストラクがありません。次のようにallocメソッドを実行してmyObjインスタンスを作ります。次の行のinitはmyObjインスタンスの初期化メソッド(イニシャライザ)です。
MyClass *myObj = [MyClass alloc];
myObj = [myObj init];
[MyClass alloc]と[myObj init]は、Objective-Cでもっとも特徴的なメッセージ式と呼ばれる書式をしています。

メッセージ式
[オブジェクト メソッド]

[MyClass alloc]の式によってMyClassクラスのallocメソッドを実行します。しかし、MyClassクラスにはallocメソッドが定義されていません。ここで先のMyClassクラス定義のヘッダファイルをもう一度よく見てください。

MyClass.hファイル
#import <Foundation/Fundation.h>

@interface MyClass:NSObject
- (void)hello;
@end

:NSObjectという部分は、MyClassクラスがNSObjectクラスを継承していることを示しています。継承はJavaならば「MyClass extends NSObject」と書きますね。
そうです。allocメソッドはNSObjectクラスから継承しているクラスメソッドです。NSObjectクラスは、Objective-Cのすべてのクラスのルートクラスであり、継承したい特定のクラスがない場合には、NSObjectクラスをスーパークラスとして指定する決まりになっています。

[MyClass alloc]を実行するとMyClassのインスタンスが作られますが、このままではまだmyObjを利用できません。[myObj init]を実行することでmyObjが初期化され、インスタンスとして使えるようになります。allocメソッドはNSObjectクラスのクラスメソッドですが、initメソッドはNSObjectクラスで定義されているインスタンスメソッドです。
インスタンスの作成と初期化は必ず実行する手順なので、先の式は次のように1行で記述するのが一般的です。

Objective-Cでのインスタンスの作成と初期化
MyClass *myObj = [[MyClass alloc] init];
ところで、myObjの前の*はタイプミスではありませんよ。オブジェクトを入れる変数は*を付けて宣言するのです。別の言い方をすれば、*はアドレスを参照する値を示しています。

さて、インスタンスの作り方がわかったところで、MyClassで定義したhelloメソッドを実行するところまで見ておきましょう。

Javaでhelloメソッドを実行する
myObjに対してドットシンタックスでhello()メソッドを実行します。
MyClass myObj = new MyClass(); //myObjを作る
myObj.hello(); //helloメソッドを実行する

Objective-Cでhelloメソッドを実行する
先ほどインスタンスを初期化するためにinitインスタンスメソッドを使ったので、もうわかりますね。
メッセージ式を使ってmyObjのhelloメソッドを実行します。hello()のようにカッコが付かない点にも注意しましょう。
MyClass *myObj = [[MyClass alloc] init]; //myObjを作る
[myObj hello]; //helloメソッドを実行する

Objective-Cのクラス定義にはまだ謎がたくさんありますが、それはまた改めて書くことにします。
オブジェクト指向言語であるActionScript3を使いこなせる人ならば、Objective-Cの学習は早いと思います。しかし、ActionScript3の知識が邪魔してObjective-Cで迷ってしまうという部分も少なからずあります。ActionScript3を使える人がObjective-Cを習得するための近道として、ActionScript3とObjective-Cとを比較してみましょう。

まずはクラス定義のコードを比較してみます。

ActionScript3のクラス定義
ActionScript3でMyClassを定義するならば、クラス名と同名のMyClass.asを作り、次のような構造のコードを記述します。
package{
  public class MyClass{

  //コンストラクタ
  public function MyClass(){
  }

  //インスタンスメソッド
  public function hello():void{
    trace("ハロー");
  }
}
Objective-Cのクラス定義
Objective-CでMyClassを定義する場合は、ヘッダファイルのMyClass.hと実装ファイルのMyClass.mの2つのファイルを使います。簡単に言えば、ヘッダファイルには他のクラスからアクセスできるプロパティやメソッドの宣言文を書き、実装ファイルでプロパティの値の設定、メソッドの定義文を書きます。

ヘッダファイル MyClass.h
#import <Foundation/Fundation.h>

@interface MyClass:NSObject
- (void)hello;
@end

実装ファイル MyClass.m
#import "MyClass.h"

@implementation MyClass

- (void)hello{
  NSLog(@"ハロー");
}

@end

Objective-Cではpackageが指定してないとか、メソッドにfunctionがないとか、メソッドが-になっているとか、いろいろ突っ込みどころがありますが、ActionScript3のクラス定義とは大きな違いがあるのに気付きますか?
それは、Objective-Cのクラス定義にはコンストラクタがないという点です。ActionScript3のクラス定義でもコンストラクタを省略できますが、Objective-Cにはコンストラクタそのものがありません。では、どうやってクラスのインスタンスを作るのでしょう?次にインスタンスを作る方法を比較してみます。

ActionScript3でインスタンスを作る
ActionScript3ではnewキーワードでMyClassコンストラクタを呼び出すとインスタンスが返ります。
MyClass myObj = new MyClass();
Objective-Cでインスタンスを作る
Objective-Cにはコンストラクがありません。次のようにallocメソッドを実行してインスタンスを作ります。
MyClass *myObj = [MyClass alloc];
myObj = [myObj init];
[MyClass alloc]と[myObj init]は、Objective-Cでもっとも特徴的なメッセージ式と呼ばれる書式をしています。

メッセージ式
[オブジェクト メソッド]

[MyClass alloc]の式によってMyClassクラスのallocメソッドを実行します。しかし、MyClassクラスにはallocメソッドが定義されていません。ここで先のMyClassクラス定義のヘッダファイルをもう一度よく見てください。

MyClass.hファイル
#import <Foundation/Fundation.h>

@interface MyClass:NSObject
- (void)hello;
@end

:NSObjectという部分は、MyClassクラスがNSObjectクラスを継承していることを示しています。継承はActionScriptならば「MyClass extends NSObject」と書きますね。
そうです。allocメソッドはNSObjectクラスから継承しているクラスメソッドです。NSObjectクラスは、Objective-Cのすべてのクラスのルートクラスであり、継承したい特定のクラスがない場合には、NSObjectクラスをスーパークラスとして指定する決まりになっています。

[MyClass alloc]を実行するとMyClassのインスタンスが作られますが、このままではまだmyObjを利用できません。[myObj init]を実行することでmyObjが初期化され、インスタンスとして使えるようになります。インスタンスとして使えるようになります。allocメソッドはNSObjectクラスのクラスメソッドですが、initメソッドはNSObjectクラスで定義されているインスタンスメソッドです。
インスタンスの作成と初期化は必ず実行する手順なので、先の式は次のように1行で記述するのが一般的です。

Objective-Cでのインスタンスの作成と初期化
MyClass *myObj = [[MyClass alloc] init];
ところで、myObjの前の*はタイプミスではありませんよ。オブジェクトを入れる変数は*を付けて宣言するのです。別の言い方をすれば、*はアドレスを参照する値を示しています。

さて、インスタンスの作り方がわかったところで、MyClassで定義したhelloメソッドを実行するところまで見ておきましょう。

ActionScript3でhelloメソッドを実行する
myObjに対してドットシンタックスでhello()メソッドを実行します。
MyClass myObj = new MyClass(); //myObjを作る
myObj.hello(); //helloメソッドを実行する

Objective-Cでhelloメソッドを実行する
先ほどインスタンスを初期化するためにinitインスタンスメソッドを使ったので、もうわかりますね。
メッセージ式を使ってmyObjのhelloメソッドを実行します。hello()のようにカッコが付かない点にも注意しましょう。
MyClass *myObj = [[MyClass alloc] init]; //myObjを作る
[myObj hello]; //helloメソッドを実行する

Objective-Cのクラス定義にはまだ謎がたくさんありますが、それはまた改めて書くことにします。

新しいObjective-Cの本が出ます!

iPhoneアプリ開発の基礎を学びながら、プログラミングのイロハからオブジェクト指向プログラミングまで自然に勉強できます。Xcodeの使い方、Objective-Cの初歩からApp Store販売までのフローをズバリ解説。

ズバわかり! プログラミング Objective-C iPhoneアプリ開発 スタートブック Xcode5.1+iOS7.1対応
大重 美幸
4800710472

目次は・・・

入門ノート(Xcode5+iOS7対応)p525正誤表

Chapter10-5 p525の下の「リスト: delegateプロパティの設定」に肝心なコードが省略されて掲載されていませんでした。コメント文の次にdelegeteを設定するコードがあります

// _myMapViewのデリゲートになる

_myMapView.delegate = self;

(略)

シェイクで実行する

iPhoneを振る(シェイクする)と1〜6の数字をデバッグエリアに出力するサイコロを作ってみます。 使用するのはUIResponderクラスのmotionBegan:withEvent:メソッドです。
iOSシミュレータではハードウェアメニューのシェイクジェスチャーで試せます。

ViewControllerクラスはUIViewControllerクラスをスーパークラスにしていますが、そのUIViewControllerクラスのスーパークラスはUIResponderクラスです。したがって、ViewControllerクラスはmotionBegan:withEvent:メソッドをオーバーライドして利用できます。

iPhoneをシェイクするとmotionBegan:withEvent:メソッドが実行され、第一引数のmotionにモーションにUIEventSubtypeMotionShakeが入っています。

実装ファイルは次のとおりです。
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// 継承しているUIResponderクラスのメソッド
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    //モーションがシェイクのときに実行する
    if(motion == UIEventSubtypeMotionShake){
        int num = arc4random()%6 + 1;
        NSLog(@"num %d", num);
    }
}

@end

iOSデベロッパーサイトからダウンロードしたiOSベータ版でiPhoneをアップデートする方法を説明しますただし、iOSベータ版でiPhoneをアップデートする場合には注意が必要です。

重要です!注意!
iPhoneをiOSベータでいったんアップデートすると、iPhoneを元の正規版のiOSに戻すことができなくなります。iOSベータでアップデートしたiPhoneは、そのままベータ版iOSでアップデートを繰り返して利用を続けます。(低いバージョンのiOSへとダウングレートできないからです)
そして次のバージョンのiOSが正式にリリースされた時点で、iOSデベロッパーサイトで公開されるGM版のiOSアップデートファイルを使って正規版にアップデートします。通常のiOSアップデートの方法では、正規版の次期iOSバージョンにアップデートすることはできません。(インストールされているiOSはすでにアップデート済みと見なされるため)

以上の注意点を理解した上で、次の手順でiPhoneをベータ版のiOSでアップデートしてください。なお、ベータ版をインストールできるiPhoneは、iOSデベロッパーサイトに開発用デバイスとして登録してあるものだけです。

前準備:

  1. iPhoneを開発用のデバイスとして登録しておく。
  2. iPhoneに合ったiOSベータのアップデートファイルをダウンロードする。
  3. ダウンロードしたdmgファイルを解凍してディスクイメージをマウントする。
アップデート作業:
  1. iPhoneを開発用のMacに接続し、iTunesで選択する。
  2. optionキーを押したままで、「アップデートを確認」ボタンをクリックする。
  3. ダウンロードしたipswファイルを選択して開く。
  4. 適合性がチェックされて、iOSのアップデートが開始する。
  5. iPhoneが再起動し、アクティベーションが行われる。←SIMが必要
  6. Home画面が表示される

iTunes_iOSupdate1_shiji.png

iPhoneモデルを特定する方法

有料のiOSデベロッパーになるとiOS、Xcodeをベータ版からテストすることができるようになります。どちらもiOSデベロッパーサイトからダウンロードするわけですが、iOSはデバイスごとに違います。デバイスがiPhone4なのかiPhone5sなのかiPadなのかというざっくりした違いではなく、製造年や販売国などによってモデルが細かく分かれています。

iosbeta.png

iPhoneの裏を見ると小さな字で「Model xxxx」と書いてあります。アップルの次のページでiPhoneの種類とモデル番号を照らし合わせれば、デバイスのモデルを特定できます。

iPhone モデルの特定
iphonemodel.png

iPadはこちら→ iPad モデルの特定