「詳細!Objective-C iPhoneアプリ開発入門ノート」のKindle版が発売になりました!
いつでもどこでも読めますよ (^^)
CodeIQにObjective-Cの問題を出題しました。問題は2問あります。
1問目は難易度2(4段階)、2問目は難易度3です。どちらも日付から曜日を求める問題ですが、2問目は実際にはクラス拡張の方法を試す問題です。CodeIQに登録しなくても問題を見ることができるようにしてあります。どちらも6月9日が締めきりです(それ以降は問題を見ることができなります)。
ぜひ、チャレンジしてみてください!
1問目 日付から曜日を求めよう(東京オリンピックの開会式が何曜日なのかを求めます)
2問目 クラス拡張の第3の方法
ただし、正解を知るには登録して解答を提出する必要があります。答えがわからない人ほど正解が知りたいでしょうが、CodeIQはそういうシステムなのでぼくにはなんとも・・・(^^;;
では、両者のクラス定義のコードを比較してみます。
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のクラス定義
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のクラス定義にはまだ謎がたくさんありますが、それはまた改めて書くことにします。
5/2発売の「ズバわかり!プログラミング Objective-C iPhoneアプリ開発スタートブック」の見本が到着しました!
ゴールデンウイーク中に発売になります。本屋で手にとってみてくださいね!
新しいObjective-Cの本が出ます!
iPhoneアプリ開発の基礎を学びながら、プログラミングのイロハからオブジェクト指向プログラミングまで自然に勉強できます。Xcodeの使い方、Objective-Cの初歩からApp Store販売までのフローをズバリ解説。
ズバわかり! プログラミング Objective-C iPhoneアプリ開発 スタートブック Xcode5.1+iOS7.1対応
大重 美幸
目次は・・・
Chapter10-5 p525の下の「リスト: delegateプロパティの設定」に肝心なコードが省略されて掲載されていませんでした。コメント文の次にdelegeteを設定するコードがあります
// _myMapViewのデリゲートになる
_myMapView.delegate = self;
(略)
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デベロッパーサイトに開発用デバイスとして登録してあるものだけです。
前準備:
- iPhoneを開発用のデバイスとして登録しておく。
- iPhoneに合ったiOSベータのアップデートファイルをダウンロードする。
- ダウンロードしたdmgファイルを解凍してディスクイメージをマウントする。
- iPhoneを開発用のMacに接続し、iTunesで選択する。
- optionキーを押したままで、「アップデートを確認」ボタンをクリックする。
- ダウンロードしたipswファイルを選択して開く。
- 適合性がチェックされて、iOSのアップデートが開始する。
- iPhoneが再起動し、アクティベーションが行われる。←SIMが必要
- Home画面が表示される
有料のiOSデベロッパーになるとiOS、Xcodeをベータ版からテストすることができるようになります。どちらもiOSデベロッパーサイトからダウンロードするわけですが、iOSはデバイスごとに違います。デバイスがiPhone4なのかiPhone5sなのかiPadなのかというざっくりした違いではなく、製造年や販売国などによってモデルが細かく分かれています。
iPhoneの裏を見ると小さな字で「Model xxxx」と書いてあります。アップルの次のページでiPhoneの種類とモデル番号を照らし合わせれば、デバイスのモデルを特定できます。
iPadはこちら→ iPad モデルの特定