第6回 iPhone勉強会
113年5月25日土曜日
・第7回 MapKitを使った地図の表示方法ブラウザでGoogleMapを表示する
今後の予定
213年5月25日土曜日
iPhone勉強会も残す所あと2回となりました。(予定ですが)少しは楽しくなってきたのであればとてもうれしいです。
・前回の復習(UITableView)・UITableView続き(データの追加と削除)・データの保持・現在地の取得方法・MapKitの使用方法・実機転送方法
今日のアジェンダ
313年5月25日土曜日
今日のスケジュールは以下の通りです。
前回の復習を行った後、UITableViewの続きを行います。地図フレームワークMapKitの使用方法について説明していきます。今日の目標は実機にアプリを流し込んで、現在地を取得して地図を表示することです。もしかしたら、UITableViewの続きで終わってしまうかも・・・。
よろしくおねがいいたします。
前回の復習
4
TODO名にはNSString型を使い、期日にはNSDate型を使いましょう。([NSDate date]で現在時刻がとれます
13年5月25日土曜日
それでは前回の復習です。この画面のように、TODOListを表示するアプリを作成しましょう。初期化のときに表示するTODOを設定してください。
詳細画面で行った編集が反映されるようにしましょう。DO名にはNSString型を使い、期日にはNSDate型を使いましょう。([NSDate date]で現在時刻がとれます
NSDictionary
5
復習で作成するアプリでは複数のデータを保持します。データの数分配列を作ると管理がしにくいです。NSDictionaryを使用し、NSDictionaryを配列にします。
NSDictionaryはJavaでいうHashMapのようなものです。キーに対応する値が格納されています。
todoName iOS勉強
Valuekey
13年5月25日土曜日
復習編で作成するアプリでは、TODO名と日付という複数のデータを格納することに気づいたでしょうか。それぞれNSArrayを作成しても良いのですが、データの種類が多くなると管理もしにくいです。そこで、NSDictaionaryを使用して、NSDictionaryをNSArrayに設定するようにしましょう。
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”];
UITableView(続き)
7
地図へ行く前に・・・
もう少しUITableViewの続きを勉強します
これで履歴画面や設定画面が作れるようになります
13年5月25日土曜日
早く地図の勉強をしたい所ですが、地図情報を取得する勉強の前に、少しだけテーブルビューの続きを行います。これで履歴画面や設定画面を作れるようになるので、より便利なアプリが作れるようになるかと思います。
UITableView(続き)
8
~データの編集を行う為にやること~
•UITableViewを編集可能にする
•追加ボタン/削除ボタンが押されたときや行が入れ替えられたときの動作を実装
13年5月25日土曜日
地図情報を取得する勉強の前に、少しだけテーブルビューの続きを行います。前回までの勉強でUITableViewでテーブルの内容を表示し、中身を更新することが出来るようになりました。ただ、新しい行を追加したり、今までのデータを削除したりしたい。ですよね・・・。UITableViewには行の追加や削除、順番の入れ替えを行うことが出来ますが、やることが二つあります。一つ目はUITableViewを編集可能にすることが必要です。もう一つは追加、削除ボタンが押されたときや行が入れ替えられたときの動作を実装する必要です。
編集モードを変更するには
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という値が変更されます。
このようになりましたか?
10
ボタンを押すことにより編集モードが変わる
13年5月25日土曜日
実装できましたか?TableViewを表示しているViewControllerのviewDidLoadに 以下のコードを追加してみましょう。self.navigationItem.rightBarButtonItem = self.editButtonItem;
右上にボタンが表示されるはずです。Editボタンを押すと表示が変わると思います。実行してみましょう。ボタンを押すことにより、編集モードが変更されているのです。
UINavigationBarって?
11
画面の上にあるこの部分のこと。
配置されているボタンのことをUINavigationButtonItemという。
13年5月25日土曜日
ここで、NavigationBarって何ものかということについて説明します。UINavigationBarは画面の上部分にあります。NavigationBarには左右のボタンがあらかじめ配置されており、設定によって表示/非表示を変更することが出来ます。self.navigationItem.rightBarButtonItem = self.editButtonItem;とは「右側のボタンを編集ボタンにします。」ということだったのです。
UINavigationController
12
画面遷移のためのViewControllerをスタックするもの(これがあるから前のViewに戻れる)
segueをpushに設定する=ViewControllerをスタック
13年5月25日土曜日
ここで、UINavigationControllerについて少し説明しておきます。UINavigationControllerは画面遷移のために、ViewControllerをためておく(スタックしておく)ものです。そうすることによって、前に表示した画面に戻ることが出来るのです。StotyBoardでsegueをpushに設定するということは、ViewControllerをスタックしているということなのです。storyBoardでsegueをpushに設定した場合、UINavigationControllerが無い状態(embed inしていない状態)だとエラーになって落ちてしまう理由が何となくわかるでしょうか。
行の削除を行う
13
削除(挿入)が実行されると・・・
削除または挿入によって引数のeditingStyleが変わる
•UITableViewCellEditingStyleDelete→削除•UITableViewCellEditingStyleInsert→挿入
commitEditingStyleメソッドが呼ばれる
13年5月25日土曜日
ではボタンが出来たので、削除処理を実装してみましょう。削除または挿入ボタンを押されるとcommitEditingStyleメソッドが呼ばれます。削除か挿入かの区別は引数のeditingStyleで出来ます。削除の場合、editingStyleがUITableViewCellEditingStyleDeleteとなり、挿入の場合はeditingStyleがUITableViewCellEditingStyleInsertとなります。新規追加は別の画面で行いますので、ここでは削除のみ実装します。
データの削除を行うには
14
元になるデータの削除→NSMutableArrayのremoveObjectAtIndexを使う
テーブルからデータの削除→UITableViewのdeleteRowsAtIndexPathsを使う
順番を逆にするとアプリが落ちるので、要注意
13年5月25日土曜日
データの削除を行うにはやることが2つあります。まず、元になるデータの削除を行います。ここでは、シングルトンで持っているNSMutableArrayから該当のデータを削除します。データの削除にはremoveObjectAtIndexメソッドを使いましょう。次に、テーブルからデータの削除を行います。テーブルからデータを削除するには、UITableViewのdeleteRowsAtIndexPathsを使います。削除対象のデータをNSArrayに設定します。このような記述を行うとTableViewからデータが削除されます。[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
ここで注意しなくてなはならないのは「元になるデータを先に削除する」ということです。deleteRowsAtIndexPathsを呼ぶと、すぐにUITableViewがリロードされるからです。先に削除しておかないと、元になるデータと行数が合わずにアプリが落ちてしまいます。
行の入れ替えを行うには
15
•UITableViewを行入れ替え可能にする→canMoveRowAtIndexPathでYESをリターンする
•行が入れ替えられたときの動作を実装→moveRowAtIndexPathメソッドが呼ばれるNSMutableArrayのexchangeObjectAtIndexメソッドで元となるデータの入れ替えを行う
13年5月25日土曜日
行の入れ替えを行うには2つやることがあります。まず、UITableViewを行入れ替え可能にします。UITableViewが行の入れ替えを可能にしているかというのはcanMoveRowAtIndexPathで返却する値によって決まります。つまり、canMoveRowAtIndexPathで返却する値がYESであれば入れ替えが可能ですし、NOであれば入れ替えが不可能になります。ここでは編集モードがONのときだけ入れ替えが実行できるようにしましょうcanMoveRowAtIndexPathメソッドのリターン値をself.editingを返却してあげればいいのです。
このようになりましたか?
1613年5月25日土曜日
では、今のことをふまえて実装をしてみましょう。実装した結果、右端に「Edit」というボタンが表示され、ボタンを押すと右の図のようになってデータの削除と入れ替えが出来るようになっているでしょうか。
データの追加を行う
17
データの追加を行う前に・・・詳細画面をこんな風に変更しましょう
Editボタンが押されたら編集画面へ遷移する
13年5月25日土曜日
では、今のことをふまえて実装をしてみましょう。実装した結果、右端に「Edit」というボタンが表示され、ボタンを押すと右の図のようになってデータの削除と入れ替えが出来るようになっているでしょうか。
StoryBoardの変更
18
詳細画面は読み取り専用にし、editボタンが押されたら編集画面へ遷移①
②
Backボタンはつけない
13年5月25日土曜日
まず、StoryBoardの変更を行います。新しくViewControllerを追加し、TODO名と期日を表示できるようにしましょう。①と書いてある箇所を参考にしてみてください。今まで詳細画面として使っていた画面は「編集画面」として使います。①の画面のNavigationbarに「edit」というボタンを追加し、ボタンを押したら編集画面に遷移できるようにします。ちなみに、バックボタンは表示しないようにしてください。②の画面を選択して Editor→Embed in→NavigationControllerを選択しておきましょう。こうすることでNavigationBarにボタンを配置することが出来ます。Cancel とSaveを配置しておきましょう。
ソースコードの変更
19
•編集画面用のViewControllerを作成
•詳細画面のViewControllerを変更
13年5月25日土曜日
それではソースコードの変更を行います。やることは大きく2つあります。編集画面用のViewControllerを作成詳細画面用のViewControllerを変更
20
•saveボタンが押されたときの処理→シングルトンで持っているデータを変更し、画面を閉じる
編集画面用ViewController
•cancelボタンが押されたときの処理→画面を閉じる
画面を閉じるにはdismissViewControllerメソッドをつかう
13年5月25日土曜日
編集画面用のViewControllerを作成します。基本的には今まで使用していた詳細画面の処理と同じものを使用したうえで、saveボタンが押されたときとcancelボタンが押されたときの処理を追加します。saveボタンが押されたときにはSingletonで持っているデータを変更し、その上で画面を閉じます。画面を閉じるときはdismissViewControllerAnimatedメソッドを使いましょう。では、実装してみてください。
追加画面を実装
21
+ボタンが押されたら編集画面へ遷移する
プラスボタンが押された場合も編集画面に遷移するようにしましょう
13年5月25日土曜日
では、プラスボタンが押された場合も編集画面に遷移するようにしましょう。StoryBoardを変更し、プラスボタンが押されたときに編集画面に遷移するようにしてみてください。この場合も戻るボタンはありません。
ソースコードの変更
22
•リスト画面用ViewControllerの変更prepareForSegueメソッドを変更し、詳細画面に遷移する場合と編集画面に遷移する場合で処理を分ける
処理を分けるにはsegue.identifierの値で区別するつまり、StoryBoardの変更も必要
13年5月25日土曜日
それではソースコードの変更を行います。まず、リスト画面用のViewControllerを変更します。いままでは一つの画面にしか遷移をしなかったのですが、今回は詳細画面に遷移する場合と編集画面に遷移する場合があるので、処理を分けます。処理を分けるにはsegueに識別子をつけて区別するようにします。ということは、StoryBoardの変更も必要になりますsegueの部分を選択し、識別子をつけましょう。詳細画面を表示する場合と編集画面を表示する場合の両方に識別子を入れます。
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; }
編集用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]; }
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"];
このようになりましたか?
2613年5月25日土曜日
今のをふまえて実装してみましょう。このようにデータの追加が出来るようになったでしょうか。
データの保持
27
ここではNSUserDefaultを使いましょう
•変更したデータを端末に保持するにはいくつか方法があるCoreData,SQLite,UserDefaultなど・・・
13年5月25日土曜日
今までの方法ではアプリを落としたらデータが初期化されていました。データを保持するにはいくつか方法があるのですが、ここでは一番簡単な方法を紹介します。Userdefaultsを使います。
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];}
位置情報の取得
29
位置情報に必要なものといえば・・・
緯度と経度
緯度と経度を取得するにはCoreLocataionFrameworkを使用する
13年5月25日土曜日
では、これから位置情報の取得方法について説明します。位置情報に必要なものは何でしょうか。緯度と経度ですね。緯度と経度を取得するには、CoreLocationFrameworkです。XCodeにCoreLocationFrameworkを追加してみましょう。
位置情報の取得
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;
位置情報の取得フロー
31
startLocationUpdate
didUpdateLocations
stopLocationUpdate
アプリ内でメソッド実行
位置が更新されたという通知
13年5月25日土曜日
アプリ内でstartLocationUpdateメソッドを実行すると位置更新が開始され、位置が更新されるとdidUpdateLocationsメソッドが呼ばれます。位置更新の必要がなくなったらstopLocationUpdateを呼ぶと、位置更新が止まります。(バッテリーの消費も激しいので、必要の無いときは位置更新を止めておきましょう)
このようなアプリを作ります
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]; }
シミュレータでの一更新
33
シミュレータのデバッグ→位置→位置情報をカスタマイズで緯度経度を変更可能
13年5月25日土曜日
シミュレータでも現在地の更新は可能です。シミュレータのメニューから位置情報をカスタマイズという画面を表示し、緯度、経度を変更することが出来ます。
地図を表示する
34
地図を表示するにはMapKitFrameworkを使います
MKMapViewで地図を表示する
13年5月25日土曜日
では今度は地図を表示してみましょう。地図を表示するには、MapKitFrameworkが必要なので、XCodeに追加します。新しくプロジェクトを作って、MapKitFrameworkとCoreLocationFrameworkを追加します。ViewController上にMKMapViewとボタンを配置し、ボタンを押したら位置の更新を開始します。
地図を表示する
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];
では、実装してみましょう。
このようになったでしょうか
3613年5月25日土曜日
このように現在地に地図の中心を合わせることが出来るようになったでしょうか。
ご清聴ありがとうございました
3713年5月25日土曜日
Top Related