iPhoneアプリ開発講座を受講する その2
[iPhone][Objective-C]
2日目は「通知」ネタを中心にやった。
1つはObsererで、もう1つはDelegate。
今回はそこの実装の仕方をまとめておく。
事例としてはそこで必要?という感もあるけど、あくまでも実装方法の確認程度ということで。
Observer
監視対象(監視される側) Class A(ScoreManager.m)
addメソッドでscoreが更新されたタイミングで何かしたいなら・・・。
-(void)add { //値が変わる前にメッセージを飛ばす [self willChangeValueForKey:@"score"]; score_ += 10; //値が変わった後にメッセージを飛ばす [self didChangeValueForKey:@"score"]; }
通知を貰う側 Class B(RootViewController.m)
scoreに変化があったタイミングで、表示を変更する感じ。
Class Aさんに自分自身を渡したるぜ〜。この「@"score"」が合図な。
- (void)viewDidLoad { ...... [scoreManager_ addObserver:self forKeyPath:@"score" options:0 context:nil]; ...... }
受け取る人
//Observerでメッセージをうけとる -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { //文字列の比較はメソッドで if ([keyPath isEqualToString:@"score"] == YES){ NSLog(@"変わった!"); [scoreLabel_ setText:[NSString stringWithFormat:@"%d", scoreManager_.score]]; } }
Delegate
デリゲートを実現するポイントは以下の3つ。
- プロパティを用意する
- プロトコルでメソッドを定義する
- 呼び出し元と呼び出し先の実装
実装してみる。
- プロパティを用意する
@property(nonatomic,assign) id <ScoreManagerDeleagate> delegate;
- プロトコルでメソッドを定義する
@protocol ScoreManagerDeleagate <NSObject> @optional -(void)scoreManagerDidSubmit:(ScoreManager*)scoreManager; @end
- 呼び出し元と呼び出し先の実装
呼び出し元(RootViewController.m)
自身をデリゲートオブジェクトとして登録する
- (void)viewDidLoad { ..... scoreManager_.delegate = self; ..... }
デリゲートメソッドを実装する
-(void)scoreManagerDidSubmit:(ScoreManager *)scoreManager { NSLog(@"submit完了しました"); }
このイベントが開始されると呼び出し先で、上記のメソッドが呼ばれる
-(void)didSubmit { [scoreManager_ submit]; }
呼び出し先(ScoreManager.m)
デリゲートが登録されているか?
デリゲートが叩きたいメソッドを持っているか?
上記を満たしているのあれば、デリゲートメソッドを呼んであげる
-(void)reset { if(delegate_ != nil){ if ([delegate_ respondsToSelector:@selector(scoreManagerDelegateReset:)]) { //delegateのメソッドを実行 [delegate_ scoreManagerDelegateReset:self]; } } }
メモリ解放
Delegate、Observer共にreleaseだけでは足りなく、
登録解除〜って呪文を唱えておかないと、急に呼ばれてアボーンってこともあるので注意
-(void)dealloc { //delegateのrelease時 scoreManager_.delegate = nil; //observerのrelease時はremoveする [scoreManager_ removeObserver:self forKeyPath:@"score"]; [scoreManager_ release]; [super dealloc]; }
というわけで、通知に関してはこの2点を教えてもらった。