I phoneアプリ入門 第4回

801 views

Published on

iPhoneアプリ開発勉強会第4回資料です

  • Be the first to comment

  • Be the first to like this

I phoneアプリ入門 第4回

  1. 1. 第4回 iPhone勉強会13年3月17日日曜日
  2. 2. 今後の予定 ・第5回 TableView続き ・第6回 ユーザ操作(タップなど)の検出方法 現在地の取得方法 ・第7回 MapKitを使った地図の表示方法 ブラウザでGoogleMapを表示する13年3月17日日曜日
  3. 3. 今日のアジェンダ ・前回の復習 ・protocolとdelegate ・テーブルビュー ・タイマー(一定時間ごとに処理を実行) ・サンプルアプリ作成13年3月17日日曜日今日のスケジュールは以下の通りです。まず、前回の復習を軽く行った後、キーパッドの閉じかたとデリゲートについて勉強します。その後、テーブルビューについて勉強します。タイマーについては時間があったら行う予定です。今日も手を動かしていきましょう。よろしくおねがいします。
  4. 4. 前回の復習 ∼以下のようなアプリを作ってみましょう∼ 動かすと文字色が変わる 押すと次の画面へ移動する13年3月17日日曜日まず、前回の復習をしましょう。前回受講したという前提で、まずはコードを書いてみます。図のようなアプリを作ってみましょう。iPhone上でボタンを押したら次の画面が表示される次の画面ではRGBをスライダーで設定し、設定した値が最初の画面に反映される・前回やったシングルトンを使います。何のことだかさっぱりわからないと言う方、こっそり教えてください・・・。
  5. 5. 前回勉強したこと • 強い参照と弱い参照 →循環参照が発生するものにはweakを使う    • MVCモデル →Model/View/Controllerの3つで役割分担 • シングルトン →プログラム中でオブジェクトを一つだけもつ13年3月17日日曜日前回学習したことを少し思い出してみましょう前回はこの3つのことについて勉強しました。・強い参照と弱い参照→Objective-Cはリファレンスカウンタ方式をとっており、オブジェクトが誰からも参照されなくなったら、メモリから解放されるのですが、オブジェクト同士が参照し合っている場合はいつまでもメモリから解放されず、メモリリークを起こしてしまいます。StoryBoardでviewに部品を配置する場合など、オブジェクト同士が参照し合う場合は弱い参照(weak)を使ってスコープ外のオブジェクトをメモリから消してしまいます。MVCモデル→Objective-CではMVCモデルを使って、Model/View/Controllerの3つで役割分担をしています。Model:データの保持や更新を行うView:Modelの内容を表示するController:ユーザ操作を受け付けたり、Modelの操作を行う・シングルトンJavaでもよく出てくるデザインパターンで、オブジェクトを一つだけ持つものです。
  6. 6. protocolとdelegate ∼機能を追加しましょう∼13年3月17日日曜日では、ここで復習で作ったアプリに機能を1つ追加しましょう。色の変更だけでなく、表示する文字列を変更するようにしてみましょう。2番目に表示される画面で文字入力を行ってその結果を最初の画面に反映するようにしましょう。2番目の画面ではテキストフィールドというものを使いましょう。
  7. 7. キーパッドを閉じるには キーパッドが閉じないのは不便・・・13年3月17日日曜日使ってみて、不便に思ったことは無いでしょうか。「キーパッドが閉じてくれない」「入力してもすぐに反映してくれない」この2つはキーパッドを閉じるという機能を実装していない為に発生しています。では、キーパッドを閉じるようにしましょう。
  8. 8. リターンキーでキーパッドを閉じる リターンキーを押されたことを検知する UITextFieldDelegate を使って検知 キーパッドを閉じる13年3月17日日曜日リターンキーを押したときにキーパッドを閉じるには図のような処理フローになります。アプリでリターンキーを押されたことを検知したらキーパッドを閉じるという処理を行うのです。リターンキーを押されたということを検知するには、UITextFieldDelegateというprotocolを使う必要があります。
  9. 9. protocolって オブジェクトの役割や振る舞いを表すメソッド の集合実装は各オブジェクト内で行う  →Javaでいうインターフェース iOSのSDKに定義されているprotocolを使うことも 自分で作ることも出来る。13年3月17日日曜日protocolというと、ネットワークの世界ではおなじみですが、Objective-Cの世界では、オブジェクトの役割や振る舞いを表すメソッドの集合のことをさします。メソッド名および引数のみヘッダファイルに設定しており、実装は各オブジェクト内で行います。Javaでいうインターフェースと同じだと考えてください。元々はオブジェクト同士の通信規約のことでしたが、だんだん意味が広くなったようです。iOSのSDKに定義されているプロトコルを使うことも自分でプロトコルを作ることも出来ます。
  10. 10. protocolの使用例 同じメソッドでもオブジェクト によって動作を変える 再生する DVD Player iPod13年3月17日日曜日protocolはどのように使用するのでしょうか。ご存知の方には釈 に説法かと思いますが念のため説明します。Javaでいうinterfaceのように同じメソッドでもオブジェクトによって処理を変えたい場合に使います。例えば同じ「再生する」という動作でもDVDプレーヤーで再生する場合とiPodで再生する場合、機械のなかで行っている処理は異なっている訳です。ただし、使う側は機械のなかで行っている処理についてはあまり気にしません。「再生する」という行為を行えば目的を達成できるのです。
  11. 11. protocolの使用例 他のオブジェクトに通知などの メッセージを送る オブジェクトA オブジェクトB 「テキストの中身変わったよ」 「リターンキーおされたよ」13年3月17日日曜日先ほどの例を応用し、Objective-Cではこんな使い方をします。あるオブジェクトから他のオブジェクトに対して通知を行うのです。例えばオブジェクトAが「自分の持っているテキストの内容が変わった」という内容の通知を行うことが出来るのです。UITextFieldの場合、「リターンキーが押された」という通知を行うことが出来ます。
  12. 12. UITextFieldDelegate UITextField.hを開いてください @protocolから@end までに書かれたメソッドが プロトコルになる テキスト プロトコルで設定している メソッド。実際の処理は実装 側で書く13年3月17日日曜日プロトコルが何なのかということがわかった所で、実際に使うものを見ていきましょう。UITextField.hを開いてください。Xcodeの左側のウィンドウからFrameworksというディレクトリを開き、UIKit.frameworkを開いてください。そこにUITextField.hというヘッダがあるのでそれを開きましょう。ファイルの下の方に@protocolUITextFieldDelegateという記載があると思います。@protocolと書くとここから@endまでの間に書いているメソッドはプロトコルだということをコンパイラに知らせています。UITextFieldの場合、テキストの編集が終わった場合の動作やリターンキーを押されたときの動作について、メソッド名だけ記載しておき、実際の処理は実装側に委譲しているのです。
  13. 13. ∼ここまでのまとめ∼ •UITextFieldDelegateというprotocolを使う •リターンキーが押されるとtextFieldShouldReturn が呼ばれる •textFieldShouldReturnの実処理は自分で実装する13年3月17日日曜日「リターンキーが押された」ことを検知するということについてこれまでのことをまとめておきましょう。まず、UITextFieldDelegateというプロトコルを使います。UITextFieldDelegateというプロトコルには”textFieldShoudReturn”というメソッドがあり、リターンキーを押されたときに呼ばれます。このメソッドは定義だけされているので、キーパッドを閉じるという処理は委譲先のオブジェクトで行う必要があります。
  14. 14. 実装方法 ■使用するprotocolの設定 UITextFieldを配置したほうの.hファイルに 以下の記述を追加する @interface クラス名:親クラス <使用するプロトコル> 使用するプロト @interface SecondViewController : コルを記載 UIViewController<UITextFieldDelegate>13年3月17日日曜日では実際の実装方法を解説していきましょうまず、使用するプロトコルを宣言します。UITextFieldを配置した方の.hファイルに以下の記述を記載し、このクラスでは”UITextFieldDelegate”を使いますよ。ということを宣言します。@interface クラス名 :親クラス <使用するプロトコル>という形式で記載してください。ここでは@interface SecondViewController : UIViewController<UITextFieldDelegate>と記載します。
  15. 15. 実装方法 ■メソッドの実処理 UITextFieldを配置したほうの.mファイルに 以下の記述を追加する #リターンキーを押されたときの処理を実装する - (BOOL)textFieldShouldReturn:(UITextField*)textField{  //キーパッドを閉じる処理を実行する  [textField resignFirstResponder]; return NO; } キーパッドを 閉じるメソッド13年3月17日日曜日ではメソッドの実処理の実装していきましょう。UITextFieldを配置した方の.mファイルにリターンキーが押されたことを検知する「textFieldShouldReturn (UITextField*)texField」メソッドを書きます。キーパッドを閉じるには「resignFirstResponder」というメソッドを呼びます。
  16. 16. この状態でコンパイルしてみましょう キーパッドは閉じたでしょうか??? 実はもう一つやることがあるのですが、 何でしょうか???ちょっと考えてみましょう。13年3月17日日曜日この状態でコンパイルして実行してみましょう。キーパッドは閉じたでしょうか・・・。実はもう一つやらなくてはならないことがあるのですが、何でしょうか。ちょっと考えてみましょう。
  17. 17. 何が足りないのか? UITextFieldDelegateを使うことにしたものの、 textFieldShouldReturnメソッドで行う処理を どこに委譲すればいいかわからない オブジェクト ??? 「リターンキー押したよ」 って誰に処理をしてもらえば いいんだ???13年3月17日日曜日UITextFieldを使うUITextFieldDelegateをつかうということを宣言したのはいいのですが、textFieldShouldReturnをどこに委譲するかを設定していなかったため、処理が委譲されていなかったのです。textFieldShouldReturnの呼び出しもととしては、誰が処理を行ってくれるかわからなかったため、処理をすることが出来なかったのです。
  18. 18. では、どうすればいいのか??  UITextFieldのdelegate(委譲元) と委譲先のViewControllerを接続する13年3月17日日曜日ではどうすればいいのでしょうか。処理の委譲先を設定してあげればいいのです。StoryBoardを開いてみましょう。TextFieldを選択し、コントロールキーを押しながらViewControllerに向けてドラッグします。そうすると図のように黒い窓が出てくると思います。そこでdelegateを選択してください。ここで何をしているかというと「textFieldShouldReturn」をViewControllerで行ってもらいますよという設定をしているのです。
  19. 19. まとめると・・・ 1.UITextFieldDelegateを使うことを宣言 2.textFieldShouldReturnメソッドを実装 3.UITextFieldのdelegateにViewControllerを設定13年3月17日日曜日ここまでのことをまとめると、以下のようになります。まず、ViewControllerで「UITextFieldDelegateを使いますよ」という宣言をします。ヘッダファイルの最初に@interface クラス名:親クラス <使用するプロトコル>という形式で記載します。ViewControllerでtextFieldShouldReturnメソッドを実装します。ここでresignFirstResponderというメソッドを呼び、キーパッドを閉じる処理を行います。そして、UITextFieldのdelegateにViewControllerを設定します。StoryBoardの設定を行いましょう。
  20. 20. TableView ∼このようなViewのことをいいます∼ 赤で囲んだ部分:UITableView 青で囲んだ部分:UITableViewCell UITableViewに UITableViewCellが含まれている13年3月17日日曜日次にTableViewの作り方について学んでいきます。TableViewの説明をし始めると長くなるので、残り時間も考えて今日は簡単なTableViewの作り方を学んでいき、次回に続きを行います。TableViewとはどのようなものかというと、図のように複数行の表示を行うViewのことです。       赤で囲んだ部分をUITableViewといい、テーブル全体のことをさします。青で囲んだ部分はUITableViewCellといい、1つの行のことをさします。UITableViewにUITableViewCellが含まれているイメージです。
  21. 21. StoryBoardを変更 TableViewControllerを 使うので、削除13年3月17日日曜日では、簡単なTableViewを作成していきましょう。新しいプロジェクトを作成してください。プロジェクトを作成したら、デフォルトで作成されるViewControllerを削除します。ViewController.m、ViewController.hとStoryBoardにあるViewControllerを削除してください。削除する際は「Move to trash」を選択していただいてかまいません。
  22. 22. TableViewControllerの作成 UITableViewController を継承する13年3月17日日曜日デフォルトで作成されたViewControllerを削除したら、TableViewControllerを作成しましょう。ファイルを新しく作成します。作成するときにUITableViewControllerのサブクラスとして作成してください。
  23. 23. StoryBoardを変更 作成したクラス名にする TableViewControllerを ドラッグして配置する13年3月17日日曜日ソースコードを作成したら、StoryBoardを変更します。StoryBoardを開いて、右部分のTableViewControllerをドラッグします。ドラッグして配置したら、CustomClassを作成したクラス名にしてください。
  24. 24. この状態で実行してみましょう 何も無い空っぽのテーブル が表示される13年3月17日日曜日この状態でビルドしてみましょう。エラーは発生していませんが、何も表示されない空っぽのテーブルが表示されているかと思います。テーブルの外枠しか設定しておらず、テーブルの中身が無いので当然といえば当然です。これからは中身を表示できるようにしてみましょう。
  25. 25. テーブルの中身を表示する 中身を表示するにはどうすればいいのか?? その前に、TableViewの仕組みについて触れて おきます。13年3月17日日曜日さすがに中身の無いTableViewを表示するのも寂しいので、中身を表示させるようにしていきます。その前に、少しTableViewの仕組みについて触れていきます。
  26. 26. テーブルの中身を表示する StoryBoardの編集 TableView Content:Dynamic:Prototypes PrototypeCells:1 TableViewCell Identifier:Cell Style:Basic13年3月17日日曜日まずStoryBoardの設定を行います。StoryBoardを開き、TableViewを選択してください。その状態で右のメニューを表示します。右から3番目のマークを選択して、図のような状態になるようにします。ContentにDynamicPrototypesを選択し、PrototypeCellsに1を設定してください。ここで何をしているかというと、「このテーブルビューでは行の数を可変にするか固定にするか」ということを設定します。ここでは「Dynamic:Prototypes」を選択しているので、行の長さを可変とし、ソースコード内で行数を変更することが出来るようにしています。PrototypeCellsの設定でテンプレートとなるセルの数を決めています。同じテーブル内でもセルの表示を変更することが出来ます。ここでは同じテンプレートを使いますので、1にします。TableViewの下にあるTableViewCellを選択してください。その状態で右のメニューを開き、図のような設定を行ってください。IdentifierにCellと設定し、StyleにBasicを設定しましょう。Identifierとはテーブルのテンプレートを決めるものです。このテンプレートの名前は「Cell」ですということを示しています。
  27. 27. テーブルの中身を表示する ソースコードの編集 次の3つのメソッドを編集します - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 指定したTableのsection数 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 指定したSectionの行数 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 指定した箇所のセル13年3月17日日曜日次にソースコードの編集を行います。まず、numberOfSectionsInTableViewというメソッドで、指定されたTableに何個セクションがあるかを呼び出し元に伝えます。このメソッドが実装されていない場合は1が返却されます。tableViewnumberOfRowsInSectionというメソッドで、指定されたSectionに何行あるかを呼び出し元に伝えています。このメソッドは必ず実装してください。実装しないとエラーになります。tableViewcellForRowAtIndexPathというメソッドで指定されたIndexPath(セクションと行)のセルを呼び出し元に伝えています。このメソッドも必ず実装してください。実装しないとエラーになります。
  28. 28. テーブルの中身を表示する 図解すると・・・ 青い線で囲んだ部分 →1つのセクション 黄色い線で囲んだ部分 →セクション1つにある行 赤い線で囲んだ部分 →1つのセル13年3月17日日曜日青い線で囲んだ部分が一つのセクションで、セクション数はnumberOfSectionsInTableViewで指定します。黄色い線で囲んだ部分がセクション内のすべての行で、指定したセクションの行数はtableViewnumberOfRowsInSectionで指定します。赤い線で囲んだ部分が指定したセクションおよび行数に該当する一つのセルで、tableViewcellForRowAtIndexPathで指定します。
  29. 29. テーブルの中身を表示する ソースコードの編集 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; ここではsection数=1 } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2; } ここでは行数213年3月17日日曜日それではソースコードの編集をしましょう。まず、 numberOfSectionsInTableViewとnumberOfRowsInSectionを編集します。セクション1つで2行表示するようにしましょう。どう指定すればいいでしょうか。。。
  30. 30. テーブルの中身を表示する ソースコードの編集 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; if(indexPath.row == 0){ cell.textLabel.text = @"上のセル"; 指定したテンプレートから } else{ Cellを作成 cell.textLabel.text = @"下のセル"; } return cell; } indexPath.rowで何行目かが わかる13年3月17日日曜日それではソースコードの編集をしましょう。次に、tableView cellForRowAtIndexPathを編集します。まず、「 dequeueReusableCellWithIdentifier」でテンプレートからCellを作成します。そして、何行目かによって表示するものを変えます。indexPath.rowと指定すると、何行目かがわかりますので行数に寄って表示するものを変えましょう。UITextViewCellにはtextLabelというラベルが標準でありますので、そちらを変更します。
  31. 31. テーブルの中身を表示する この状態でコンパイルしてみましょう このような表示になりました か??13年3月17日日曜日この状態でコンパイルしてみましょう。うまく表示されましたでしょうか?
  32. 32. テーブルの中身を表示する if文で表示するCellを場合分けしていると きりがない・・・ NSArrayを使う →JavaでいうArrayListと同じ使い方をする13年3月17日日曜日
  33. 33. NSArrayの使い方 arrayWithObjectsで初期化 NSArray *list = [NSArray arrayWithObjects:@"AAA",@"BBB",nil]; ※他にも初期化メソッドはあります objectAtIndexで指定したIndexのオブジェクトを取得 [list objectAtIndex:0];  ※ここでは@”AAA”が返ってくる countでオブジェクトの数を取得 [list count];  ※ここでは2が返ってくる13年3月17日日曜日NSArrayの使い方について触れておきます。まず、初期化メソッドを使って初期化します。arrayWithObjectsを使うと指定したオブジェクトでNSArrayを初期化できます。objectAtIndexで指定したIndexのオブジェクトを取得します。countでオブジェクトの数を取得します。
  34. 34. NSArrayは読み取り専用 編集したいときはNSMutableArrayを使う addObjectでオブジェクトを追加 [list addObject:@”AAA”; //最後にオブジェクトを追加 insertObjectでオブジェクトを挿入 [list insertObject:@”AAA” atIndex:1]; //1番目にオブジェクトを挿入 removeObjectAtIndexでオブジェクトを削除 [list removeObjectAtIndex:1]; //1番目のオブジェクトを削除 replaceObjectAtIndexでオブジェクトを変更 [list replaceObjectAtIndex:1 withObject:@”BBB”];  //1番目のオブジェクトを@”BBB”に変更13年3月17日日曜日ただし、NSArrayは読み取り専用のため、編集が出来ません。編集したいときはNSMutableArrayを使います。「Mutable」がついているオブジェクトは編集可能ということです。使い方はJavaのArrayListと似ており、追加、挿入、削除、交換などが出来ます
  35. 35. では、NSArrayを使って セルの中身を変更してみましょう13年3月17日日曜日
  36. 36. 一定時間ごとに処理を行う NSTimerを使うと一定間隔で同じメソッドを呼び 出すことが出来る [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(increment:) userInfo:nil タイマーを初期化して開始す repeats:YES]; るメソッド [timer invalidate]; タイマーを止めるメソッド [timer fire]; タイマーを開始するメソッド13年3月17日日曜日第2回目でリクエストがあった、「一定時間ごとに値が更新されるプログラム」について説明をします。NSTimerというクラスを使うと、一定時間間隔で同じメソッドを呼び出すことが出来ます。お渡ししたファイルにNSTimerTestというプロジェクトがありますので、そちらをご覧ください。
  37. 37. 一定時間ごとに処理を行う @selectorって何?? →コンパイラに「この引数はメソッドである(SEL 型)」ことを示すもの [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(increment:) userInfo:nil repeats:YES]; incrementというメソッドを 渡している13年3月17日日曜日ここで@selectorについて少し解説します。@selectorとはコンパイラに対して「この引数はメソッド(関数)である」ということを教えています。SEL型と言います。ここで使用しているNSTimerでは自分自身のメソッドを繰り返し呼び出しています。
  38. 38. ご清聴ありがとうございました13年3月17日日曜日

×