サンプル漁りのススメ : iOS Advent Calender 2011

さて、2011年のiOS Advent Calenderが書かれ始めてもう6日目ですね。みなさますごくコアなネタを仕込んでらっしゃってとても面白く読ませてもらってます。これからのCalenderも楽しみですね。
6日目の今日はバンバン開発されている方には物足りないし、長ったらしいし、オチがアレな感じなのですが、ご了承ください^^;;;

対象読者

さて、私がiOS開発始めて1年ちょっと経ちました。とはいえアプリ開発が本業ではないため、私はコアなネタは書けないのですが、初心者が入門書を読んだ後に何を作っていいかわからない、どう作っていいかわからないといった状態の方に向けて、これはやっとくといいぞ!というネタを書いてみました。

※他のAdvent Calenderを未読な方で、この記事に直接飛んでこられた方はまずは@TeamMOSA2さんによる「iOSゆとりプログラミングのすすめ」を読んでからの方がきっと気合いの入り方が違うと思います(笑

入門書を読んでも、「iOSゆとりプログラミングのススメ」を読んでもそれだけではアプリを作れるようにはなりません。Hello world程度ならすぐに出来ますが、そんなのばっかりではきっと飽きてしまうでしょう。かといって、入門レベルが終わったあとの中級レベルへの入門書が有るかと言えば、僕は見た事有りません。Objective-Cの辞書だったり、マッシュアップだったり、データベース作成などの本が有りますが、これらはある程度アプリ作成のハウツー(死語?w)をある程度持っている人、勉強してきている人向けなんじゃないかなぁなんて個人的には思います。

では、入門書を読み終わって、いざアプリを作ろうとしても出来ないひと-文法やクラスなどは理解できてきたけれど、実際にどうやってそれらを組み合わせるとアプリが出来上がるのかわからない人が次にやるといいと思うこと、それはサンプルコード漁りです。




アップルにはとても豊かなサンプルコードライブラリーが有りますので使わない手はないでしょう。Google先生ばかりに頼っては見えないモノがあります。

サンプルはここで漁れ!

iOS Developer Library Sample Code

iOS Developer Library(日本語訳)

オンラインじゃなくとも、XCodeのドキュメントにも入っているので、オフラインでもサンプルコードが漁れます。

サンプルコードはFrameworkやAudioなどといった種類ごとに分類分けされているので、これから作りたいアプリのジャンルのサンプルをダウンロードしてきて、まずはBuild and Goして実際に触ってみるのが楽しいんじゃないかな。

では、実際に漁ってみましょう。

作りたいものを決めます。

電卓!

私のアプリは今後電卓シリーズになりそうなので電卓のサンプルを探してきました。
ちなみにGoogleで検索できるObjective-Cによる電卓のサンプルコードとしてはこの辺があげられますが、動くんですがエラーが出ちゃうんですよ、動くけど。Appleが出しているサンプルの中にも電卓のコードがあるんです。Calculatorで探しても出て来ないんですが(^^;。

iPhoneUnitTestsというサンプルの中に電卓のコードが入っています。
ここからダウンロードしてきて、まずは見てみましょう。

iPhoneUnitTests

プロジェクトファイルを開いてターゲットをiOS_Calcにし、Build and Goしてみてください。

普通に使える電卓が表示されましたね。

機能を追加してみよう

では、この電卓にiPhone標準の電卓のようにスワイプすると1桁消すような機能を付けてみましょう。スワイプやタップを検出するUIGestureRecognizerを使えばいいので、そのサンプルもダウンロード。

SimpleGestureRecognizers

サンプルを見るとUIGestureRecognizerはタップやスワイプで何かをしたい、反応させたいViewにaddGestureRecognizerでGestureを足してやればいい、もしくはiOS5からInterfaceBuilderで使えるようになったGesture Recognizer をXibファイルに入れてやればいいということがわかりますね。えっ?わかりますね?わからない人はもうちょっと入門書読みましょう!

じゃあ、これらを先ほどのiPhoneUnitTestsプロジェクトでも真似してみましょう。

iPhoneUnitTestsのなかのiOS_CalcViewControllerが表示を司るViewControllerなので、ここにUISwipeGestureRecognizerを突っ込みます。

UITextFieldのGestureRecognizerにSwipeGestureRecognizerをくっつけます。

iOS_CalcViewController.hに下記のように追記。

#import <UIKit/UIKit.h>
#import "Calculator.h"

//UIGestureRecognizerDelegateを使うので追記
@interface CalcViewController : UIViewController { 
id          displayField;
Calculator *calculator;
}

@property (nonatomic, retain) IBOutlet id displayField;
//左から右にスワイプする動作を登録
@property (nonatomic, strong) IBOutlet UISwipeGestureRecognizer *swipeLeftRecognizer;
- (IBAction)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer; //スワイプしたら呼ばれる。
- (IBAction) press:(id)sender;
@end

iOS_CalcViewController.mには下記を追記。

@synthesize swipeLeftRecognizer=_swipeLeftRecognizer;
- (IBAction)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer{
NSLog(@"スワイプしたよ");
}

そしてSwipeGestureRecognizerとIBActionをヒモつける。

これだけで電卓にSwipeGestureがくっつきます。

ここでUITextFieldをスワイプするとコンソールログに「スワイプしたよ」と表示されるはずです。

電卓の構造解析

次に、このサンプル電卓に表示されている文字はどのように表示されているのでしょうか。その仕組を知らないと「スワイプで右端の文字を消す」という目標が達成できませんね。

iPhoneUnitTestのサンプルコードを読んでみましょう。

まず、xibファイルを見ていきます。
CalcView.xibを開いてみてください。そして適当なボタンの上で右クリックもしくはcommand+クリックしてみてください。下のような画面が出ると思います。

UIButtonのTouchUpInside(ボタン内で指が離された)イベント時にpress:が呼ばれていることがわかります。このxibのFile’s OwnerはiOS_CalcViewControllerなので、その中のpress:メソッドが呼ばれているのでしょう。詳しく見て行きましょう。

iOS_CalcViewController.mの最後にこのような記述がありますね。

- (IBAction) press:(id)sender {
   [calculator input:[sender titleForState:UIControlStateNormal]];
   [displayField setText:[calculator displayValue]];
}

一体何をしているかというと、1行目でcalculator(計算を司るクラス)に押された文字のタイトル(0とか)を渡して計算させ、calculatorクラスのdisplayValueというメソッドを実行し、その戻り値をdisplayFieldのTextにセットしている事がわかります。

では、calculatorクラスのdisplayValueメソッドは何をしているのでしょうか。

サンプルコード内の「Calculator-iOS > CalculatorLib-Engine > Calculator.m」を見てください。

#pragma mark Outlets

/*
 * The displayValue method rerutns a copy of _display.
 */
- (NSString *) displayValue {
   if ([_display length]) {
      return [[_display copy] autorelease];
   }
   return @"0";
}

_displayにデータが入っていたらその文字列(NSString)を返すメソッドですね。
では、_displayとは何者なんでしょう?

同じファイルの先頭を見てみると初期化メソッドがあります。

- init {
   if ((self = [super init])) {
      _display = [[NSMutableString stringWithCapacity:20] retain];
      _operator = nil;
   }
   return self;
}

_displayは上限が20文字に限定されたNSMUtableStringですね!
じゃあ、この_displayの一番最後の文字を消す処理を書けばいいかもしれないね!
ってことが想像できませんか?

「スワイプをすると一文字消える電卓」を作るまで、あと少しです。

だが、しかし!ここからは宿題です!

工エエェェ(´д`)ェェエエ工

だってそのまま答え載せたら「ふ〜ん、こうやれば動くんだ」なんて納得して手動かさないでしょ?そうなるの、わかってるんだから。

    宿題!

  • スワイプしたら一番右の文字が削除されるようにしてください。
  • 左右どちらからのスワイプにも対応してみてください。
  • 0で割ると「エラー」と表示するようにしてみてください。

  • ヒント1:SwipeGestureが発生した時に表示されている文字列の最後(NSMutableStringの最後の文字列)を削除したものを表示すれば完成ですね?ほんとですか?w
  • ヒント2:サンプルコード「SimpleGestureRecognizers」内のスワイプ有効・無効判定処理らへん。
  • ヒント3:(ry

頑張ってみてください。

まとめ

入門書を読み終わって、なんとな〜〜くアプリの作り方がわかった方には「iOS SDKにはどんなクラスがあってどんなメソッドがどのような使い方をされるのかが分からない」っていう人が結構いらっしゃると思います。そんな方々にはぜひ、今回のようにサンプルコードをいじってみて欲しいと思います。

Apple純正のサンプルコードは実際に実機でも動かせるコードですし、なんて言ったってAppleによるアプリ審査時にリジェクトされないコードでもあると思います。

初めてサンプルコードを読んだときはわからない事だらけです。でもそれが当たり前です。分からないことは辞書的なiOSの参考書なりAppleのForumなり、札幌の方でしたらDevSapに聞けばいいと思います。

大事なのはとにかく動かして見て理解すること。これに尽きると思います。

お粗末ではありますが、上記のサンプルコードを置いておきます。

質問などは随時受け付けております。@Guttyoにメンション飛ばしていただければ返答できると思います。

今回の記事がみなさんのお役に立てれば幸いです。