37
第6回 iPhone勉強会 1 13525日土曜日

I phoneアプリ入門 第6回

Embed Size (px)

DESCRIPTION

iPhone勉強会で使用した資料です。

Citation preview

Page 1: I phoneアプリ入門 第6回

第6回 iPhone勉強会

113年5月25日土曜日

Page 2: I phoneアプリ入門 第6回

・第7回 MapKitを使った地図の表示方法ブラウザでGoogleMapを表示する

今後の予定

213年5月25日土曜日

iPhone勉強会も残す所あと2回となりました。(予定ですが)少しは楽しくなってきたのであればとてもうれしいです。

Page 3: I phoneアプリ入門 第6回

・前回の復習(UITableView)・UITableView続き(データの追加と削除)・データの保持・現在地の取得方法・MapKitの使用方法・実機転送方法

今日のアジェンダ

313年5月25日土曜日

今日のスケジュールは以下の通りです。

前回の復習を行った後、UITableViewの続きを行います。地図フレームワークMapKitの使用方法について説明していきます。今日の目標は実機にアプリを流し込んで、現在地を取得して地図を表示することです。もしかしたら、UITableViewの続きで終わってしまうかも・・・。

よろしくおねがいいたします。

Page 4: I phoneアプリ入門 第6回

前回の復習

4

TODO名にはNSString型を使い、期日にはNSDate型を使いましょう。([NSDate date]で現在時刻がとれます

13年5月25日土曜日

それでは前回の復習です。この画面のように、TODOListを表示するアプリを作成しましょう。初期化のときに表示するTODOを設定してください。

詳細画面で行った編集が反映されるようにしましょう。DO名にはNSString型を使い、期日にはNSDate型を使いましょう。([NSDate date]で現在時刻がとれます

Page 5: I phoneアプリ入門 第6回

NSDictionary

5

復習で作成するアプリでは複数のデータを保持します。データの数分配列を作ると管理がしにくいです。NSDictionaryを使用し、NSDictionaryを配列にします。

NSDictionaryはJavaでいうHashMapのようなものです。キーに対応する値が格納されています。

todoName iOS勉強

Valuekey

13年5月25日土曜日

復習編で作成するアプリでは、TODO名と日付という複数のデータを格納することに気づいたでしょうか。それぞれNSArrayを作成しても良いのですが、データの種類が多くなると管理もしにくいです。そこで、NSDictaionaryを使用して、NSDictionaryをNSArrayに設定するようにしましょう。

Page 6: I phoneアプリ入門 第6回

NSDictionary

6

初期化(alloc initでもよい)dictionary:空のDictionaryを作る

データの参照objectForKey: (id)keyキーに(key)該当するデータを取得する

データの設定(NSMutableDictionary)setObject :(id)object forKey:(id)key 引数keyをキーobjectを該当オブジェクトとするエントリを追加する

13年5月25日土曜日

NSDictionaryにはいろいろなメソッドがありますが、主なものを紹介します

初期化メソッドNSDictionary *dict = [[NSDictionary alloc] init];NSDictionary *dict = [NSDictionary dictionary];

データの参照NSString *toDo = (NSString*)[dict objectForKey:@”todoName”];

データの設定(NSMutableDictionaryを使う)[dict setObject:toDo forKey:@”todoName”];

Page 7: I phoneアプリ入門 第6回

UITableView(続き)

7

地図へ行く前に・・・

もう少しUITableViewの続きを勉強します

これで履歴画面や設定画面が作れるようになります

13年5月25日土曜日

早く地図の勉強をしたい所ですが、地図情報を取得する勉強の前に、少しだけテーブルビューの続きを行います。これで履歴画面や設定画面を作れるようになるので、より便利なアプリが作れるようになるかと思います。

Page 8: I phoneアプリ入門 第6回

UITableView(続き)

8

~データの編集を行う為にやること~

•UITableViewを編集可能にする

•追加ボタン/削除ボタンが押されたときや行が入れ替えられたときの動作を実装

13年5月25日土曜日

地図情報を取得する勉強の前に、少しだけテーブルビューの続きを行います。前回までの勉強でUITableViewでテーブルの内容を表示し、中身を更新することが出来るようになりました。ただ、新しい行を追加したり、今までのデータを削除したりしたい。ですよね・・・。UITableViewには行の追加や削除、順番の入れ替えを行うことが出来ますが、やることが二つあります。一つ目はUITableViewを編集可能にすることが必要です。もう一つは追加、削除ボタンが押されたときや行が入れ替えられたときの動作を実装する必要です。

Page 9: I phoneアプリ入門 第6回

編集モードを変更するには

9

のですが、ここでは手っ取り早い方法をとります。UITableViewControllerのeditButtonItem(編集ボタン)をNavigationBarの右側に配置すればOK

コードはこんな感じ。ViewControllerの初期処理で実装してみてください。(どこに書けば良いのかは考えてみましょう)self.navigationItem.rightBarButtonItem = self.editButtonItem;

UITableViewのsetEditingメソッドを使う

13年5月25日土曜日

まず、UITableViewの編集モードを変更しましょう。UITableViewのsetEditingメソッドを実装すると編集モードの変更が出来ますが、UITableViewControllerには便利なものがありますので、紹介します。UITableViewControllerにはeditButtonItemを押すことで編集モードに切り替えるボタンが実装されています。なので、そのeditButtonItemをNavigationBarに配置すればよいのです。editButtonItemを押すことでUITableViewControlleのeditingという値が変更されます。

Page 10: I phoneアプリ入門 第6回

このようになりましたか?

10

ボタンを押すことにより編集モードが変わる

13年5月25日土曜日

実装できましたか?TableViewを表示しているViewControllerのviewDidLoadに 以下のコードを追加してみましょう。self.navigationItem.rightBarButtonItem = self.editButtonItem;

右上にボタンが表示されるはずです。Editボタンを押すと表示が変わると思います。実行してみましょう。ボタンを押すことにより、編集モードが変更されているのです。

Page 11: I phoneアプリ入門 第6回

UINavigationBarって?

11

画面の上にあるこの部分のこと。

配置されているボタンのことをUINavigationButtonItemという。

13年5月25日土曜日

ここで、NavigationBarって何ものかということについて説明します。UINavigationBarは画面の上部分にあります。NavigationBarには左右のボタンがあらかじめ配置されており、設定によって表示/非表示を変更することが出来ます。self.navigationItem.rightBarButtonItem = self.editButtonItem;とは「右側のボタンを編集ボタンにします。」ということだったのです。

Page 12: I phoneアプリ入門 第6回

UINavigationController

12

画面遷移のためのViewControllerをスタックするもの(これがあるから前のViewに戻れる)

segueをpushに設定する=ViewControllerをスタック

13年5月25日土曜日

ここで、UINavigationControllerについて少し説明しておきます。UINavigationControllerは画面遷移のために、ViewControllerをためておく(スタックしておく)ものです。そうすることによって、前に表示した画面に戻ることが出来るのです。StotyBoardでsegueをpushに設定するということは、ViewControllerをスタックしているということなのです。storyBoardでsegueをpushに設定した場合、UINavigationControllerが無い状態(embed inしていない状態)だとエラーになって落ちてしまう理由が何となくわかるでしょうか。

Page 13: I phoneアプリ入門 第6回

行の削除を行う

13

削除(挿入)が実行されると・・・

削除または挿入によって引数のeditingStyleが変わる

•UITableViewCellEditingStyleDelete→削除•UITableViewCellEditingStyleInsert→挿入

commitEditingStyleメソッドが呼ばれる

13年5月25日土曜日

ではボタンが出来たので、削除処理を実装してみましょう。削除または挿入ボタンを押されるとcommitEditingStyleメソッドが呼ばれます。削除か挿入かの区別は引数のeditingStyleで出来ます。削除の場合、editingStyleがUITableViewCellEditingStyleDeleteとなり、挿入の場合はeditingStyleがUITableViewCellEditingStyleInsertとなります。新規追加は別の画面で行いますので、ここでは削除のみ実装します。

Page 14: I phoneアプリ入門 第6回

データの削除を行うには

14

元になるデータの削除→NSMutableArrayのremoveObjectAtIndexを使う

テーブルからデータの削除→UITableViewのdeleteRowsAtIndexPathsを使う

順番を逆にするとアプリが落ちるので、要注意

13年5月25日土曜日

データの削除を行うにはやることが2つあります。まず、元になるデータの削除を行います。ここでは、シングルトンで持っているNSMutableArrayから該当のデータを削除します。データの削除にはremoveObjectAtIndexメソッドを使いましょう。次に、テーブルからデータの削除を行います。テーブルからデータを削除するには、UITableViewのdeleteRowsAtIndexPathsを使います。削除対象のデータをNSArrayに設定します。このような記述を行うとTableViewからデータが削除されます。[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

ここで注意しなくてなはならないのは「元になるデータを先に削除する」ということです。deleteRowsAtIndexPathsを呼ぶと、すぐにUITableViewがリロードされるからです。先に削除しておかないと、元になるデータと行数が合わずにアプリが落ちてしまいます。

Page 15: I phoneアプリ入門 第6回

行の入れ替えを行うには

15

•UITableViewを行入れ替え可能にする→canMoveRowAtIndexPathでYESをリターンする

•行が入れ替えられたときの動作を実装→moveRowAtIndexPathメソッドが呼ばれるNSMutableArrayのexchangeObjectAtIndexメソッドで元となるデータの入れ替えを行う

13年5月25日土曜日

行の入れ替えを行うには2つやることがあります。まず、UITableViewを行入れ替え可能にします。UITableViewが行の入れ替えを可能にしているかというのはcanMoveRowAtIndexPathで返却する値によって決まります。つまり、canMoveRowAtIndexPathで返却する値がYESであれば入れ替えが可能ですし、NOであれば入れ替えが不可能になります。ここでは編集モードがONのときだけ入れ替えが実行できるようにしましょうcanMoveRowAtIndexPathメソッドのリターン値をself.editingを返却してあげればいいのです。

Page 16: I phoneアプリ入門 第6回

このようになりましたか?

1613年5月25日土曜日

では、今のことをふまえて実装をしてみましょう。実装した結果、右端に「Edit」というボタンが表示され、ボタンを押すと右の図のようになってデータの削除と入れ替えが出来るようになっているでしょうか。

Page 17: I phoneアプリ入門 第6回

データの追加を行う

17

データの追加を行う前に・・・詳細画面をこんな風に変更しましょう

Editボタンが押されたら編集画面へ遷移する

13年5月25日土曜日

では、今のことをふまえて実装をしてみましょう。実装した結果、右端に「Edit」というボタンが表示され、ボタンを押すと右の図のようになってデータの削除と入れ替えが出来るようになっているでしょうか。

Page 18: I phoneアプリ入門 第6回

StoryBoardの変更

18

詳細画面は読み取り専用にし、editボタンが押されたら編集画面へ遷移①

Backボタンはつけない

13年5月25日土曜日

まず、StoryBoardの変更を行います。新しくViewControllerを追加し、TODO名と期日を表示できるようにしましょう。①と書いてある箇所を参考にしてみてください。今まで詳細画面として使っていた画面は「編集画面」として使います。①の画面のNavigationbarに「edit」というボタンを追加し、ボタンを押したら編集画面に遷移できるようにします。ちなみに、バックボタンは表示しないようにしてください。②の画面を選択して Editor→Embed in→NavigationControllerを選択しておきましょう。こうすることでNavigationBarにボタンを配置することが出来ます。Cancel とSaveを配置しておきましょう。

Page 19: I phoneアプリ入門 第6回

ソースコードの変更

19

•編集画面用のViewControllerを作成

•詳細画面のViewControllerを変更

13年5月25日土曜日

それではソースコードの変更を行います。やることは大きく2つあります。編集画面用のViewControllerを作成詳細画面用のViewControllerを変更

Page 20: I phoneアプリ入門 第6回

20

•saveボタンが押されたときの処理→シングルトンで持っているデータを変更し、画面を閉じる

編集画面用ViewController

•cancelボタンが押されたときの処理→画面を閉じる

画面を閉じるにはdismissViewControllerメソッドをつかう

13年5月25日土曜日

編集画面用のViewControllerを作成します。基本的には今まで使用していた詳細画面の処理と同じものを使用したうえで、saveボタンが押されたときとcancelボタンが押されたときの処理を追加します。saveボタンが押されたときにはSingletonで持っているデータを変更し、その上で画面を閉じます。画面を閉じるときはdismissViewControllerAnimatedメソッドを使いましょう。では、実装してみてください。

Page 21: I phoneアプリ入門 第6回

追加画面を実装

21

+ボタンが押されたら編集画面へ遷移する

プラスボタンが押された場合も編集画面に遷移するようにしましょう

13年5月25日土曜日

では、プラスボタンが押された場合も編集画面に遷移するようにしましょう。StoryBoardを変更し、プラスボタンが押されたときに編集画面に遷移するようにしてみてください。この場合も戻るボタンはありません。

Page 22: I phoneアプリ入門 第6回

ソースコードの変更

22

•リスト画面用ViewControllerの変更prepareForSegueメソッドを変更し、詳細画面に遷移する場合と編集画面に遷移する場合で処理を分ける

処理を分けるにはsegue.identifierの値で区別するつまり、StoryBoardの変更も必要

13年5月25日土曜日

それではソースコードの変更を行います。まず、リスト画面用のViewControllerを変更します。いままでは一つの画面にしか遷移をしなかったのですが、今回は詳細画面に遷移する場合と編集画面に遷移する場合があるので、処理を分けます。処理を分けるにはsegueに識別子をつけて区別するようにします。ということは、StoryBoardの変更も必要になりますsegueの部分を選択し、識別子をつけましょう。詳細画面を表示する場合と編集画面を表示する場合の両方に識別子を入れます。

Page 23: I phoneアプリ入門 第6回

prepareForSegue内の処理

23

•識別子の文字列比較文字列の比較はisEqualToStringメソッドを使う

•編集画面の場合の処理遷移先はUINavigationControllerなので、UINavigationControllerのtopViewControllerから編集画面用ViewControllerを取得し、行番号の設定を行う(追加とわかるような行番号にする)

13年5月25日土曜日

prepareForSegue内の処理について説明します。まずは判定のために識別子の文字列比較を行います。文字列の比較はNSStringのisEqualToStringメソッドを使用します。詳細画面の場合は、いままでと同じ処理なのですが、編集画面の場合は同じようには出来ません。StoryBoardを見てもわかるようにUINavigationControllerを挟んでいるので、 segue.destinationViewController にはUINavigationControllerが入っているのです。UINavigationControllerのスタックの一番上にあるViewControllerを取得すれば良いのです。(1つしかないので一番上なのは当然です)編集画面へ遷移するときはデータの追加なので、indexには追加とわかるような番号にしましょう(ということは負の値にすれば良いのです)コードはこのようになります。if ([segue.identifier isEqualToString:@"DetailViewController"]) { //詳細画面用の処理 }else if([segue.identifier isEqualToString:@"EditViewController"]) { UINavigationController *navigationController = (UINavigationController *)segue.destinationViewController; EditViewController *editViewController = (EditViewController *)navigationController.topViewController; editViewController.selectedIndex = kDefaultSelectedIndex; }

Page 24: I phoneアプリ入門 第6回

編集用ViewController

24

•saveボタンが押されたときの処理追加の場合はNSMutableArrayのaddObjectメソッドでデータを追加

•画面が表示されたときの処理追加の場合はデフォルト値を表示

13年5月25日土曜日

編集用ViewControllerの変更をします。まず、画面が表示されたときの処理を実装します。何行目の値か保持しているかと思いますので、保持している値がデフォルト値だったらデータの追加とみなし、デフォルト値を表示するようにします。このような処理になります。 if(self.selectedIndex == kDefaultSelectedIndex) { // データを新規作成 _cachedData = [[NSMutableDictionary alloc]init]; // デフォルトのデータを作成する [_cachedData setObject:@"TODO" forKey:kDataKeyToDoName]; [_cachedData setObject:[NSDate date] forKey:kDataKeyToDoDate]; } else { // ToDoの詳細を取得する DataManager *dataManager = [DataManager sharedInstance]; _cachedData = [dataManager.todoList objectAtIndex:self.selectedIndex]; } 次にsaveボタンが押されたときの処理を実装します。追加の場合はNSMutableArrayのaddObjectメソッドを使ってデータを追加します。 // データを保存する DataManager *dataManager = [DataManager sharedInstance]; // indexが初期値の場合は追加 if (self.selectedIndex == kDefaultSelectedIndex){ [dataManager.todoList addObject:_cachedData]; } else { [dataManager.todoList replaceObjectAtIndex:self.selectedIndex withObject:_cachedData]; }

Page 25: I phoneアプリ入門 第6回

25

•TextFieldからLabel へ変更

詳細画面用ViewController

•日付を文字列に変換NSDateFormatterというクラスを使ってNSDate型オブジェクトから文字列を取得する

•prepareForSegueの実装何行目のデータを見ていたかというデータを渡す

13年5月25日土曜日

詳細画面用のViewControllerを作成します。TextFieldで表示を行っていたものをLabelで表示するようにしましょう。そして、編集ボタンが押されたときに何行目のデータを参照していたかという情報を渡してあげます。これにはprepareForSegueを使います。最後に日付を文字列に変換しましょう。NSDateFormatterというクラスを使うとNSDate型のオブジェクトから文字列を取得することが出来ます。

NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init]; [dateFormat setDateFormat:@"yyyy/MM/dd"];

Page 26: I phoneアプリ入門 第6回

このようになりましたか?

2613年5月25日土曜日

今のをふまえて実装してみましょう。このようにデータの追加が出来るようになったでしょうか。

Page 27: I phoneアプリ入門 第6回

データの保持

27

ここではNSUserDefaultを使いましょう

•変更したデータを端末に保持するにはいくつか方法があるCoreData,SQLite,UserDefaultなど・・・

13年5月25日土曜日

今までの方法ではアプリを落としたらデータが初期化されていました。データを保持するにはいくつか方法があるのですが、ここでは一番簡単な方法を紹介します。Userdefaultsを使います。

Page 28: I phoneアプリ入門 第6回

NSUserDefault

28

• UserDefaultの取得:standardUserDefaults• データの設定:setObject forKey• データの保存:synchronize• データの取得:arrayForKey (XXForKey)

13年5月25日土曜日

[NSUserDefaults standardUserDefaults]でUserdefaultsを取得します。setObjectメソッドでデータの設定を行い、synchronizeメソッドで保存を行います。arrayForKeyでデータの取得を行います。シングルトンのクラスにデータの保存メソッドを実装してみましょう。このようになります。- (void)saveTodoList { // todoListをUserDefaultに保存する NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setObject:_sharedInstance.todoList forKey:@"todoList"]; [userDefaults synchronize];}

Page 29: I phoneアプリ入門 第6回

位置情報の取得

29

位置情報に必要なものといえば・・・

緯度と経度

緯度と経度を取得するにはCoreLocataionFrameworkを使用する

13年5月25日土曜日

では、これから位置情報の取得方法について説明します。位置情報に必要なものは何でしょうか。緯度と経度ですね。緯度と経度を取得するには、CoreLocationFrameworkです。XCodeにCoreLocationFrameworkを追加してみましょう。

Page 30: I phoneアプリ入門 第6回

位置情報の取得

30

位置を取得するのはCoreLocationManager

現在地更新開始startLocationUpdateメソッド

現在地取得完了(delegateメソッド)didUpdateLocationsメソッドdidUpdateToLocationメソッド(iOS6より古い場合)

delegateメソッドを使うにはどうすれば良いのでしょうか

13年5月25日土曜日

位置を取得するためにはCoreLocationManagerを使用します。[[CoreLocation alloc]init]でCoreLocationManagerの初期化を行います。現在地の更新開始を行うには、startLocationUpdateメソッドを呼び出します。更新終了するにはstopLocationUpdateメソッドを呼び出します。現在地が更新されるとdidUpdateLocationsメソッドが呼び出されます。これはdelegateメソッドなので、delegateメソッドが呼ばれるようにしなくてはならないのですが、どうすれば良いのでしょうか。didUpdateLocationsには位置情報が格納されています。locataionsの最後のオブジェクトに最新の位置情報が格納されているので、取得しましょう。iOS6より古い場合はdidUpdateToLocationを使用します。

ヘッダファイルには以下のように記述します。@interface ViewController : UIViewController <CLLocationManagerDelegate>ViewControllerのviewDidLoadメソッドでこのようにdelegateを設定します。_locationManager.delegate = self;

Page 31: I phoneアプリ入門 第6回

位置情報の取得フロー

31

startLocationUpdate

didUpdateLocations

stopLocationUpdate

アプリ内でメソッド実行

位置が更新されたという通知

13年5月25日土曜日

アプリ内でstartLocationUpdateメソッドを実行すると位置更新が開始され、位置が更新されるとdidUpdateLocationsメソッドが呼ばれます。位置更新の必要がなくなったらstopLocationUpdateを呼ぶと、位置更新が止まります。(バッテリーの消費も激しいので、必要の無いときは位置更新を止めておきましょう)

Page 32: I phoneアプリ入門 第6回

このようなアプリを作ります

32

新しいプロジェクトを作成して緯度と経度を表示するアプリを作ります

ボタンを押したら位置情報取得開始

13年5月25日土曜日

では、新しいプロジェクトを作成して、緯度と経度を表示するアプリを作ってみましょう。ボタンを押したら位置情報の取得開始を行い、もう一回押したら位置情報の取得を終了します。

このようにボタンの表記を変えてみましょう。- (IBAction)startAndStop:(id)sender { NSString *buttonTitle; // 更新中でない場合 if (!_isUpdatingLocation) { // 位置取得開始 [_locationManager startUpdatingLocation]; buttonTitle = @"現在地取得終了";

} else { // 位置取得終了 [_locationManager stopUpdatingLocation]; buttonTitle = @"現在地取得開始"; } // フラグを反転 _isUpdatingLocation = !_isUpdatingLocation; // ボタンのラベルを変更する UIButton *button = (UIButton *)sender; [button setTitle:buttonTitle forState:UIControlStateNormal]; }

Page 33: I phoneアプリ入門 第6回

シミュレータでの一更新

33

シミュレータのデバッグ→位置→位置情報をカスタマイズで緯度経度を変更可能

13年5月25日土曜日

シミュレータでも現在地の更新は可能です。シミュレータのメニューから位置情報をカスタマイズという画面を表示し、緯度、経度を変更することが出来ます。

Page 34: I phoneアプリ入門 第6回

地図を表示する

34

地図を表示するにはMapKitFrameworkを使います

MKMapViewで地図を表示する

13年5月25日土曜日

では今度は地図を表示してみましょう。地図を表示するには、MapKitFrameworkが必要なので、XCodeに追加します。新しくプロジェクトを作って、MapKitFrameworkとCoreLocationFrameworkを追加します。ViewController上にMKMapViewとボタンを配置し、ボタンを押したら位置の更新を開始します。

Page 35: I phoneアプリ入門 第6回

地図を表示する

35

地図の表示には以下のメソッドを使用する※位置情報が更新された時に実行します

setCenterCoordinateメソッド中心の緯度経度を設定する

setRegionメソッド表示範囲を設定する※MKCoordinateRegionMakeWithDistanceで表示範囲を設定可能

13年5月25日土曜日

地図を表示するにはMKMapViewのsetCenterCoodinateメソッドに緯度経度を設定しますdidUpdateLocationsメソッドの引数として渡されたCLLocationsの緯度経度を中心にしてあげればよいのです。ただしこのままだと、かなり広い範囲でしか表示されないので、半径1キロメートルの範囲を表示するようにしてみましょう。範囲を設定するにはMKMapViewのsetRegionメソッドを実行します。範囲はMKCoordinateRegionMakeWithDistanceで設定できます。このようなコードになります。 // Locationを取得する CLLocation *currentLocation = [location lastObject]; // 表示範囲を設定する(半径1キロ) MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(currentLocation.coordinate, 1000.0, 1000.0); // MapViewを更新する [self.mapView setCenterCoordinate:currentLocation.coordinate]; [self.mapView setRegion:region animated:YES];

では、実装してみましょう。

Page 36: I phoneアプリ入門 第6回

このようになったでしょうか

3613年5月25日土曜日

このように現在地に地図の中心を合わせることが出来るようになったでしょうか。

Page 37: I phoneアプリ入門 第6回

ご清聴ありがとうございました

3713年5月25日土曜日