i phoneアプリ入門 第3回

32
第3回 iPhone勉強会 13317日日曜日

Upload: sachiko-kajishima

Post on 24-Jun-2015

641 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

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

第3回 iPhone勉強会

13年3月17日日曜日

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

・第3回 他の画面の値を変更する方法MVCモデル、タイマーの使い方

・第4回 TableView ユーザ操作(タップなど)の検出方法・第5回 MapKitを使った地図の表示方法

現在地の取得方法

今後の予定

13年3月17日日曜日

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

・前回の復習・他の画面の値を設定する・MVCモデル・タイマー(一定時間ごとに処理を実行)・サンプルアプリ作成

今日のアジェンダ

13年3月17日日曜日

今日のスケジュールは以下の通りです。まず、前回の復習を軽く行った後、他のオブジェクトの値変更の仕方およびMVCモデルについて説明した後、時間がありそうだったら、タイマーとテーブルビューの説明をいたします。その後、今日の課題となるサンプルアプリを作成いたします。今日も出来るだけ手を動かすようにしたいと思います。よろしくおねがいいたします。

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

~以下のようなアプリを作ってみましょう~

前回の復習

押すと次の画面へ移動する 動かすとフォントサイズが変わる

13年3月17日日曜日

まず、前回の復習をしましょう。前回受講したという前提で、まずはコードを書いてみます。図のようなアプリを作ってみましょう。iPhone上でボタンを押したら次の画面が表示される何のことだかさっぱりわからないと言う方、こっそり教えてください・・・。制限時間は20分とします。

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

他の画面の値を設定する

view1 view2fontSize

view1でview2のフォントサイズを変えたい

view2というオブジェクトにアクセスしてフォントサイズを変える

13年3月17日日曜日

ある画面で設定した値を他の画面へ反映するようにしたいと思うのではないでしょうか。図のようにview1でview2のフォントサイズを変更するという処理をするにはどうすればいいでしょうか。ここでよく思い出してみましょう。Objective-CはJavaと同じオブジェクト指向です。Javaのときはどうしていたでしょうか。。。Hoge hoge = new Hoge();hoge.setMoge(“AAA”);などとというようにオブジェクトにアクセスして値を変更していたと思います。

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

他のオブジェクトにアクセスする方法

view2fontSize

//View2というオブジェクトを作る(またはどこかからもってくる)View2 *view2 = [[View2 alloc]init];

//View2というオブジェクトのfontSizeを変更するview2.fontSize = 12;

「fontSizeを変更する」というメッセージを送る

13年3月17日日曜日

Objective-Cでもおなじことです。View2というオブジェクトを新しく作成するかまたはどこかから取得して、View2というオブジェクトに対して「フォントサイズを変更してくれ」というメッセージを送るのです。

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

「復習」での具体例

ViewController DetailViewController

DetailViewControllerの値を変更したい

どちらかをやりたいViewControllerからDetailViewControllerの値を変更DetailViewControllerからViewControllerの値を取得

13年3月17日日曜日

では、復習で行った場合の具体例を見ていきましょう。実装の都合上、ViewControllerで設定した値をDetailViewControllerで表示するというようにします。この場合ですと、ViewControllerクラスからDetailViewControllerに対してアクセスするか、DetailViewControllerクラスあらViewControllerクラスにアクセスすればいいのです。どうすればいいのでしょうか既にViewController、DetailViewControllerで画面を作っているため、オブジェクト自体を新しく作り直す訳にはいきません。いくつかやり方はあるのですが1つ紹介します。

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

ViewControllerからDetailViewControllerの値を変更する

ViewController

- (void)prepareForSegue:(UIStoryBoardSegue*)se

gue

DetailViewController

float(nonatmic) fontSize;UILabel *label

ViewControllerからDetailViewControllerに遷移するときに値を変更

13年3月17日日曜日

先ほど復習で使ったプロジェクトを編集し、ViewControllerで設定したフォントサイズでDetailViewControllerの画面を表示するようにしましょう。まず、StoryBoard画面を開いて、ViewControllerにSliderとStepperを配置し、ヘッダファイルに反映させましょう。そして、ViewController.mに- (void)prepareForSegue:(UIStoryBoardSegue*)segueというメソッドを記載してください。

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

2つのViewControllerにアクセスするメソッド

- (void)prepareForSegue:(UIStoryBoardSegue*)segueボタンを押したとき(viewを移動するとき)に呼ばれるメソッド

UIStoryBoardSegue:2つのViewControllerを行き来するときに使うオブジェクトsourceViewController:(遷移元のViewController)destinationViewController:(遷移先のViewController)

13年3月17日日曜日

- (void)prepareForSegue:(UIStoryBoardSegue*)segueはボタンを押してViewを移動するときに呼ばれるメソッドで、引数のsegueにはsourceViewControllerという遷移先のViewControllerとdestinationViewControllerという遷移先のViewControllerが格納されています。ここではdestinationViewControllerへアクセスすることで遷移先のViewControllerで保持している値を変更することが出来ます。

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

2つのViewControllerにアクセスするメソッド

- (void)prepareForSegue:(UIStoryBoardSegue*)segueヘッダファイルに宣言していないのになぜエラーにならない?

prepareForSegue はUIViewControllerで宣言されているから

13年3月17日日曜日

ViewController.mのみに - (void)prepareForSegue:(UIStoryBoardSegue*)segueを記載したと思いますが、ヘッダファイルに宣言しない状態でビルドしてもエラーになりません。なぜかというと、親クラスであるUIViewControllerで宣言されているからです。

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

ViewControllerからDetailViewControllerの値を変更する

- (void)prepareForSegue:(UIStoryBoardSegue*)segue の中身

DetailViewController *detailViewController = (DetailViewController *)segue.destinationViewController; detailViewController.label.font = [UIFont fontWithName:@"Helvetica" size:self.fontSize];

DetailViewController型にキャストしている

13年3月17日日曜日

- (void)prepareForSegue:(UIStoryBoardSegue*)segueの中身を実装しましょう。segueのdestinatinationViewControllerに遷移先のViewController(ここではDetailViewController)が格納されているので、取得してみましょう。取得したDetailViewControllerのlabelの値を変更してみましょう。この状態でコンパイルして実行します。                                                    

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

ViewControllerからDetailViewControllerの値を変更する

動かしてみて、フォントサイズは変わりましたか?

実は、これだとフォントサイズは変わらないのです。なぜでしょう・・・。

なぜか知るために、デバッグしてみましょう。

13年3月17日日曜日

コンパイルして実行してみましょう。フォントサイズは変わりましたか?変わっていませんね。なぜでしょうか。なぜか知るためにデバッグしてみましょう。Xcodeでブレークポイントを貼ってみましょう。

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

デバッガを使ってみようXcodeを立ち上げて、以下のようにブレークポイントを設定します。

detailViewController.labelがnilになっている

13年3月17日日曜日

コンパイルして実行してみましょう。フォントサイズは変わりましたか?変わっていませんね。なぜでしょうか。なぜか知るためにデバッグしてみましょう。画面のようにXcodeでブレークポイントを設定して実行してみましょう。detailViewController.labelがnilになっているのがわかりますか?nilに対して設定しても値は変わらないのです。なので、値が変わらなかったのです。

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

ここで湧く2つの疑問

■疑問その1:nilにアクセスして大丈夫なの?(そもそもnilって何)

■疑問その2:何でdetailViewController.labelがnilなの?

13年3月17日日曜日

ここで2つの疑問が湧くと思います。まず、nilにアクセスしても大丈夫なのか(そもそも、nilって何?)ということと何でdetailViewController.labelがnilなのかということです。

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

nilとは?

空のポインタ、無効なオブジェクトちなみに、値は0

メッセージを送るとどうなる?→何も送られない。

nilはid型の空ポインタで値は0

13年3月17日日曜日

ここで改めて、「nil」とは何かということを説明します。nilとは無効なオブジェクトのことで、空のポインタです。ちなみに値は0です。デバッガで表示されている値を見てみましょう。0x00000000となっていると思います。javaで言えばNULLと同じようなものなのですが、nilに対してメッセージを送っても落ちるということは無く、何も処理が行われません。なので、detailViewController.labelにアクセスしようとしても、何も行われなかったのです。

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

参照(strongとweak)

DetailViewController.hの中身

@property (weak, nonatomic) IBOutlet UILabel *label;

弱い参照を表している

strong(デフォルト):強い参照。誰も参照しなくなったらオブジェクトが消滅するweak:弱い参照。変数スコープを超えるとオブジェクトが消滅する

13年3月17日日曜日

では、なぜDetailViewControllerの中身がnilだったのでしょうか。DetailViewController.hの中身を見てみましょう。@property (weak, nonatomic) IBOutlet UILabel *labelと書かれているのではないでしょうか。ここで注目していただきたいのは、@propertyの後のweakという文字です。これはオブジェクトが強い参照か弱い参照かを表しています。デフォルトではstrongが設定されています。Objective-Cはリファレンスカウンタ方式をとっており、そのオブジェクトが誰からも参照されなくなったらメモリ上から消えるようになっています。「強い参照」ではオブジェクトが誰からも参照されなくなったらメモリから解放されます。(消滅します)「弱い参照」ではオブジェクトは変数スコープを超えるとメモリから解放されます。

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

なぜ弱い参照が必要?

Object1 Object2Object2への強い参照

Object1への強い参照

オブジェクト同士が参照し合っている状態を考えてみましょう。

これだといつまでたってもオブジェクトが解放されず、メモリリークになる

13年3月17日日曜日

なぜ、弱い参照が必要なのでしょうか。強い参照だけだと困る場合があるのです。図のようにオブジェクト同士が参照し合っている状態を考えてみます。Object1はObject2を参照し、Object2はObject1を参照します。いわゆる、循環参照という状態です。この場合、参照状態が消滅することが無いので、いつまでたってもオブジェクトが残り続けることになります。オブジェクトが残り続けるとメモリリークとなりアプリが落ちてしまう原因にもなるのでさけなくてはならないのです。

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

なぜ弱い参照が必要?

Object1 Object2Object2への弱い参照

Object1への強い参照

Object2にweakをつけて弱い参照にすると・・・

Object2はスコープを超えると消滅し、Object1に対しての参照も消滅する

13年3月17日日曜日

ここでObject2に対してweakをつけて弱い参照にするとどうなるでしょうか。Object1はObject2に対して弱い参照を持っていることになります。Object2はスコープをこえると消滅してしまい、同時にObject1への参照も消滅します。つまり、オブジェクトがいつまでも残り続けるということがなくなると言うわけです。

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

例題の場合

InterfaceBuilderでlabelを貼付けることによりDetailViewControllerのviewがlabelを参照

view labellabelへの参照

13年3月17日日曜日

例題の場合、InterfaceBuilderでlabelをviewに貼付けることで、detailViewControllerのviewがlabelを参照することになります。しかし、viewが消滅したときには貼付けているlabelを見ることはありません。なので、弱い参照としてviewが消滅すると同時にlabelも消滅させてしまうのです。

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

では、どうすればいい?DetailViewController.hに以下を追加します。@property (nonatomic)float fontSize;

そして、DetailViewController.mに以下を追加します

・viewWillAppearself.label.font = [UIFont fontWithName:@"Helvetica" size:self.fontSize];

さらに、ViewController.mに以下を追加します・prepareForSeguedetailViewController.fontSize = self.slider.value;

Viewを表示するときに呼ばれるメソッド

13年3月17日日曜日

ではどうすればいいでしょうか。labelを直接変更せず、フォントサイズを渡してあげればよいのです。DetailViewControllerでは受け取ったフォントサイズを反映します。DetailViewControllerの親クラスであるUIViewControllerでは、viewを表示する直前にviewWilAppearというメソッドが呼ばれます。そこでlabelに渡されたフォントサイズを反映させてあげればいいのです。さらにViewController.mのprepareForSegueではDetailViewControllerで定義したfontSizeの値を変更しましょう。ちなみに、fontSizeはオブジェクトではなくプリミティブな値なので、メモリは自動解放されます。なので、strongやweakをきにする必要はありません。

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

ここまでのまとめ

・他のオブジェクトの値の変更・デバッグ・nilについて・強い参照と弱い参照

13年3月17日日曜日

無事に動いたでしょうか。ここまでのおさらいをします。まず、他のオブジェクトに対して値を変更する方法を勉強しました。デバッガの起動方法も触れましたね。nilが何かということも勉強しました。強い参照と弱い参照にも触れました。ここでやったことはかなり難しいです。今すぐにすべてを理解するのは大変なので、開発がある程度で切るようになったらもう一度見直していただけるとうれしいです。

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

MVCモデル

ここで、他の値も設定するようにプログラムを変えてみましょう。

数カ所だけならまだしも、何個も変更する値があるとめんどくさい→そこでMVCモデルを使う

13年3月17日日曜日

今までの話で、画面で設定したものを他の画面へ反映する方法を学んだので、他のパーツを追加し、変更した値を反映するようにしましょう。いちいちすべての値を渡すのは大変です。一つのオブジェクトとしてまとめた方が楽です。そのような要求に応えてくれるのがMVCモデルです。これからMVCモデルについて勉強していきます。

Javaなどでも画面で設定したものをデータオブジェクトに保持するなんてことを行っているかと思います。Objective-Cでも同じです。iPhoneアプリの開発ではMVCモデルに基づいて開発します。釈迦に説法かも知れないですが、MVCモデルについておさらいします。Modelでデータの保持およびデータの操作を行います。ViewでModelのデータを画面に表示します。Controllerでユーザの操作の受付およびモデルの操作を行います。Viewに対するControllerということでViewControllerを使っていた訳です。

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

MVCモデル

Model

データおよびデータの操作

Modelのデータを画面へ表示

ユーザ操作の受付モデルの操作

View Controller

13年3月17日日曜日

Objective-Cでも同じです。iPhoneアプリの開発ではMVCモデルに基づいて開発します。釈迦に説法かも知れないですが、MVCモデルについておさらいします。Modelでデータの保持およびデータの操作を行います。ViewでModelのデータを画面に表示します。Controllerでユーザの操作の受付およびモデルの操作を行います。Viewに対するControllerということでViewControllerを使っていた訳です。

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

Modelを作成してみよう

・会員(Member)というモデルを作成

~モデルのデータ~・会員番号  変数名:memberId 型:int型・会員名  変数名:memberName 型:NSString型

このモデルを実現するオブジェクトを作成するには?

13年3月17日日曜日

ViewとControllerについては既に作成しているので、今度はViewで入力したデータを保持するモデルを作成しましょう。例えば会員(Member)というモデルを作成する例を考えてみます。モデルの中身は、int型の会員番号とNSString型の会員名とします。この場合、どのようにオブジェクトを作成するにはどうしたらいいでしょうか。

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

Modelを作成してみよう

必要なもの・.hファイル(Model.h)・.mファイル (Model.m)

・.hファイルの中身@property(nonatomic,strong) NSString *memberName;@property(nonatomic)int memberId;

13年3月17日日曜日

必要なものは.hファイルと.mファイルです。メニューのFile→New→Fileを選んで新しいファイルを作成します。Objective-C Classを選択して次に進んでください。ClassにはMember、SubClassにはNSObjectを記載して保存してください。そうすると、Model.hとModel.mが作成されます。Model.hにmemberNameとmemberIdを宣言してください。@propertyをつけるとgetterとsetterが作成されるので、特にModel.mの記載はいりません。

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

シングルトンどこからでもアクセスできるシングルトンにします。・Model.hに以下の記載を追加+(Member *)sharedInstance;

・Model.mに以下の記載を追加static Member *member = nil;

@implementation Member

+(Member *)sharedInstance{ if (member == nil) { member = [[super alloc]init]; } return member;}

13年3月17日日曜日

このままでもいいのですが、どこからでもアクセスできるようにシングルトンにします。(データを外部ファイルに保存していないので)Model.hには以下のように記載してください。+(Member *)sharedInstance;+というのは、クラスメソッドであるということです。つまり、オブジェクトではなく、クラスに対してメッセージを送るということです。ここではMemberというクラスに対してsharedInstanceというメッセージを送るとMemberがたのオブジェクトが返ってきます。Model.mファイルにはsharedInstanceメソッドの実装を行います。まず、staticをつけることにより、ファイル内だけで有効となります。(ほかのオブジェクトからアクセスできないようになります) そして sharedInstanceが呼ばれたときは、nilであるかどうかチェックをして、nilだった場合のみ初期化します。

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

値の参照方法

値を参照するには以下のように記述します

[Member sharedInstance]. memberName;

これでMember型のオブジェクトを取得

取得した値を表示させてみましょう

13年3月17日日曜日

Member型のオブジェクトに設定した値を参照するには [Member sharedInstance]を使ってオブジェクトを取得します。取得したオブジェクトの値を参照してください。MVCTestというプロジェクトをに詳細のコードを記載しておりますので、見てみましょう。

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

一定時間ごとに処理を行う

NSTimerを使うと一定間隔で同じメソッドを呼び出すことが出来る

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(increment:) userInfo:nil repeats:YES];

[timer invalidate];

[timer fire];

タイマーを初期化して開始するメソッド

タイマーを止めるメソッド

タイマーを開始するメソッド

13年3月17日日曜日

ここで前回リクエストがあったので、「一定時間ごとに値が更新されるプログラム」について説明をします。NSTimerというクラスを使うと、一定時間間隔で同じメソッドを呼び出すことが出来ます。 お渡ししたファイルにNSTimerTestというプロジェクトがありますので、そちらをご覧ください。

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

一定時間ごとに処理を行う

@selectorって何??→コンパイラに「この引数はメソッドである(SEL型)」ことを示すもの

[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(increment:) userInfo:nil repeats:YES];

incrementというメソッドを渡している

13年3月17日日曜日

ここで@selectorについて少し解説します。@selectorとはコンパイラに対して「この引数はメソッド(関数)である」ということを教えています。SEL型と言います。ここで使用しているNSTimerでは自分自身のメソッドを繰り返し呼び出しています。

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

今日のまとめ

・他のオブジェクトの値の変更・MVCモデル・タイマーの使い方

13年3月17日日曜日

では、今日の課題に入る前におさらいをしましょう最初に他のオブジェクトの値の変更する方法を勉強しました。そして、MVCモデルを使って色々な画面から値を参照できるようにしました。おまけにタイマーの使い方を勉強しました。

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

今日の課題

13年3月17日日曜日

では、今日の課題です。このようにボタンを押したら項目の編集を行い、編集結果を反映できるようにしてみてください

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

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

13年3月17日日曜日