3月からずっとプログラミングを担当していたiOS向けアプリが本日ようやくAppStoreに申請完了しました。Xcode、Objective-Cはもとより、ポインタとかオブジェクト指向プログラミング自体が初めてで本当につまづきまくりでしたが、ホッと一息です。まぁ、まだ審査という大きな壁があるわけですが、とりあえず時間は少し余裕ができるのでこちらのブログもぼちぼち再開していきたいと。
さてまずは表題。PHP、VB.NETあたりはちょいちょいやってきた(だがOOP的なことはほとんどしたことがない)視点から。慣れてしまった今とはってはそれなりによくできてると思うし、何故当初そんなにつまづいたかも徐々に忘れつつあるのですが、なんとか思い出せる範囲で書き留めておこうと思います。同じようなところでつまづいてる人の参考になれば。あと今回教えてもらった人にも「何がわからんのかわからん」と言われたので、そんな指導する側の人にも初学者の陥りがちな(?)勘違いを知らしめる意味で、恥を晒しておきます。
・宣言ファイル.hと実装ファイル.m
初心者はまずここから躓きますw。新しいクラスhogeを作ると、hoge.h、hoge.m(そしてViewControllerの場合はさらに.xibも)というファイルができます。VB脳からするとなんぞこれ?ですよね。実際のところ宣言と実装という言葉でほとんど説明できてしまってるんですが、最初はとにかく情報量が多すぎるのでこれだけでもビビります。VB的に実際のコードを書くのが実装ファイル(.m)ですね。じゃぁ.hは何かというと、そのオブジェクトが内包しているプロパティオブジェクトやメソッドの一覧が記された設計仕様書という感じ。他のクラスから利用する場合にこの.hファイルをimportしといてやると、そのクラスがもっていないメソッドを呼ぼうとした時にXcodeがそいつはそんなメソッド知らんってよ?と警告してくれます。まぁ、実際には.m側を精査すれば同じ内容は得られるんでしょうし、むしろ.mではちゃんと実装してるのに.hに書いてないからエラーになるなんて本末転倒なこともあったりするんですが、作業面でもまず.hに「こんなメソッド作るぞ-」とかToDo的に書いておけば、未実装の分はやはり警告が出るので便利っちゃ便利です。
・Interface Builder
これも慣れてしまうとどうってことないんですが、Objective-C自体がよくわかってない状態ではハマりました。Interface Builder(以下IB)で配置したボタンなどのオブジェクトを、そっくりコードの上でも宣言して、それを紐づけてやらないといけない、というのはVBにはなかったので。しかもIBAction(GUI部品から操作イベントを受け取るメソッド)とIBOutlet(コードから部品に表示を反映させる先)の双方向を別々にとか。でその方法がCtrl+ドラッグだったりと、あんまし直感的じゃなかったり。なんでもインスペクタからするVB的感覚とだいぶ違いますね。勢い解説書でもひたすら手順を説明するに留まって、読んでる方はすごく「やらされ感」が募ります。D&D操作って静止画のみの書籍での解説とは相性悪いのもあるんでしょうかね。
ただ慣れたせいかもですが、途中で導入したXcode4になってから随分やりやすくなった気がします。前バージョンだとIBは独立アプリという感じで、コードを保存しないでウインドウだけ移っても反映されてない、とか色々不便でしたし。ちょっといじってみようという人には有料になっちゃいますが、これから入門するならXcode4オススメです(一気にDeveloper Programにお布施しちゃうぞー、って人はタダです)。
個人的理解度がいまだにあやしいのはMainWindows.xibの扱いですね。まぁ、各種テンプレートを使ってプロジェクトを作った場合はほとんど触ることなさそうですが。
・delegate
これは悩みました。ググればなんなのかはいくらでも記述があるんですが、どう嬉しいのか、どういう場面で使うべきかがいまいちピンとこない。当初、親ビューなどスコープの届かない別オブジェクト(例えば大元のAppDelegate.m)の中のプロパティに上手くアクセスすることができず、仕方ないのでメソッド自体をその別オブジェクト側に移してそこで処理する為のものだと思って利用してました。だって一番最初のクラスの名前についてるしw。グローバル変数的なプロパティとそれにアクセスするメソッドを全部集めるべきか、とかw。
だが先輩プログラマ(同級生だけど)にそうではないと教わりました(hogeAppDelegate内のプロパティにアクセスする簡単な方法も教わった)。標準のクラスとはちょっとだけ違う振る舞いをするオブジェクトが欲しい時に、次々にカスタムオブジェクトを作っていくと大変(.h/.mペアがどんどん増える)なので、それをまとめて1つの.h/.mで処理するって感じですね。特にUIButton等のGUIパーツをIB上で配置すると本来は.hや.mはいらない訳ですが、そこに1つだけ特殊なことするメソッドが欲しい、なんて時に、そのボタンのdelegate(代行)先を親ビューであるViewController.mにして、そこにメソッドを書く、なんてことをします。うん、今ならこれがないと大変だということがわかる。特にUITableViewはOS側から呼ばれるイベントハンドラが多い(総行数の問い合わせとか)ので、それを実際のデータをもってるオブジェクトに“転送”したりするのに使いまくりでした。うん、イベントハンドラの転送、と考えるとしっくり来る。
・ポインタ
十数年間もσ(^^)が各プラットフォームでネイティブアプリを書く障壁となってきたポインタは、Objective-Cでは思ってたほど意識する必要なかったみたいです。宣言する時に、オブジェクトかどうか見極めて*をつけるかどうか判断する位。INTやBOOLでは不要だけど、文字列(NSString)はオブジェクトだからつけないとダメとか。プロパティやメソッドの引数を宣言するところ以外では*つけなくてもいいので、普段はあんまり意識しなかったです。
ただ高速列挙という、ある配列内のオブジェクトを順に取り出して順に処理していく方法の中で、一次変数オブジェクト作ってそれを取り出して変更を加えた後、元変数に書き戻さないといけないと思ってましたが、実際には取り出してなくてポインタをコピーしてただけなので書き戻し操作は不要だった、なんてことがありしました。
あと開発後半でリーク対策をしようという段になって、ちゃんと理解してないとダメだなと思いました。変数の感覚でポンポン“代入”をしてると、Leakテストした時にビックリしますw。
でもまぁとりあえず始めるにあたっては他のC系言語ほど怖がらなくてもヨサゲ、ってことだけは言えます(って他のC系言語実際に挑戦すらしてないけど)。
・@propertyと@synthesize
この辺も訳わか
らないウチは、なんで同じ様な宣言をあちこちで何度もやらされるんだろう?と混乱しますね。.hファイルの中でプロパティを宣言した上で、同じファイルのすぐ下で@propertyで繰り返し宣言をし、さらに.mで@synthesizeですよ。これらは主にクラス外からプロパティにアクセスする時に必要なもので、@propertyはそのヘッダーファイルをimportした他クラスに対して、自分はこんな“プロパティ”を外部に公開してるよー、と知らしめる為で、クラス内部でしかアクセスしないならなくてもいい。また@synthesizeは.mファイル側で実際にset/getするメソッドを自動で“シンセサイズ”(生成)するためのもの。@synthesize hoge;とするだけなので超簡単ですが、これを使わずに自前でメソッドを作ってもいいので、やっぱりプログラマが任意で書かなきゃダメって訳です。似てるんだけどそれぞれ役割が違う。
とまぁこの辺がちょっと壁だったような気がします。というかまだ間違ってるかも知れないので、そこは皆さん追々ちゃんと調べて勉強していって下さい(^^;)。とりあえずこんな感じで理解したら少し前に進めた気がする、ってことで。