Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

iOSハンズオントレーニング observer編 (delegate,notification,KVO)

4,243 views

Published on

Observerパターンについて、Delegate,Notification,KVOを使って実装する方法を学びます。

Published in: Technology, News & Politics
  • Be the first to comment

iOSハンズオントレーニング observer編 (delegate,notification,KVO)

  1. 1. iOSハンズオントレーニング Delegate(委譲)、Notification(通知)、KVO(キー値監視)  大久保 聡
  2. 2. 目次 Observerパターン Delegate(委譲) Notification(通知) KVO : Key-Value Observing(キー値監視)
  3. 3. Observerパターン Observerパターンに登場するのは、2つのクラスだ。 監視するクラスと、監視されて通知を行うクラスだ。 監視するクラスの方を、Observerクラスと呼ぼう。 もう一方の監視されるクラスの方は、Subjectクラ スとする。
  4. 4. Delegate(委譲) 委譲元オブジェクトのポインタを移譲先オブジェクトで 保持し、委譲先オブジェクトから委譲元オブジェクトの メソッドをコールする。・・・コールバック
  5. 5. Delegate実装 (実装イメージ) アルバムに写真を配置、写真がタップされ たらその選ばれた写真の処理をしたい。 監視側のObserverクラス 監視される側のSubject をUIView クラスをUIImageView タップされた ら親クラスの メソッドをコー ルバックする。
  6. 6. Delegate実装 (Subjectクラスの作成) UIImageViewクラスを新たに作成する。 UIImageViewクラスに、Observerクラスのポインタを 保持するメンバ変数を追加する。 ユーザ操作を受け付けるように変更する。 self.userInteractionEnabled = YES; タップされたら、Observerクラスのメソッドをコール する。 ※ベースとなるプロジェクトをダウンロードしてください。 https:/ /github.com/ovjang/NoUseStoryBoard_Observer
  7. 7. // // // PictureView.h ! #import <UIKit/UIKit.h> ! @interface PictureView : UIImageView { @private NSObject *delegate_; } ! @property NSObject *delegate; ! @end // // // PictureView.m ! #import "PictureView.h" ! @implementation PictureView @synthesize delegate = delegate_; ! - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.userInteractionEnabled = YES; // UIImageViewはデフォルトでNoなので注意 } return self; } ! - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if(delegate_ !=nil) { [delegate_ pictureSelected]; } } ! @end
  8. 8. Delegate実装 (プロトコルの作成) プロトコルを新たに作成する。 subjectクラスのメンバ変数に、プロトコルを指定 する。 タップされた際に呼ぶメソッドで、プロトコルに 準拠していることを確認する。
  9. 9. // // PictureViewDelegate.h (javaでいうところのインターフェース) // ! #import <Foundation/Foundation.h> ! @protocol PictureViewDelegate <NSObject> @optional -(void)pictureSelected; // 抽象メソッド ! @end // // // PictureView.h ! #import <UIKit/UIKit.h> #import "PictureViewDelegate.h" ! @interface PictureView : UIImageView { @private NSObject <PictureViewDelegate> *delegate_; } @property NSObject <PictureViewDelegate> *delegate; @end // // // PictureView.m ! #import "PictureView.h" ! @implementation PictureView @synthesize delegate = delegate_; ! - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.userInteractionEnabled = YES; } return self; } ! - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if(delegate_ !=nil) { if ([delegate_ conformsToProtocol:@protocol(PictureViewDelegate)]) { if ([delegate_ respondsToSelector:@selector(pictureSelected)]) { [delegate_ pictureSelected]; } } } } @end
  10. 10. Delegate実装 (Observerクラスの作成) 既存のUIViewControllerを、Observerクラスにしま す。また、プロトコルに準拠させる。 Subjectクラスを、newして画面に配置する。 Subjectクラスのメンバ変数に、自分のポインタを格納 する。 プロトコルにあるメソッドを実装する。
  11. 11. // Screen1ViewController.h ! #import <UIKit/UIKit.h> #import "PictureViewDelegate.h" ! @interface Screen1ViewController : UIViewController <PictureViewDelegate> ! @end / ! Screen1ViewController.m #import "Screen1ViewController.h" #import "PictureView.h" ! @interface Screen1ViewController () ! @end ! @implementation Screen1ViewController ! - (id)init { self = [super init]; if (self) { // Custom initialization self.title = @"Album"; self.view.backgroundColor = [UIColor grayColor]; } return self; } ! - (void)viewDidLoad { [super viewDidLoad]; UIImage* image01 = [UIImage imageNamed:@"picture01.jpeg"]; PictureView* uiImageView1 = [[PictureView alloc] initWithFrame:CGRectMake(10, 10, 100, 150)]; uiImageView1.delegate = self; uiImageView1.image = image01; [self.view addSubview:uiImageView1]; ! UIImage* image02 = [UIImage imageNamed:@"picture02.jpeg"]; PictureView* uiImageView2 = [[PictureView alloc] initWithFrame:CGRectMake(120, 10, 100, 150)]; uiImageView2.delegate = self; uiImageView2.image = image02; [self.view addSubview:uiImageView2]; } ! -(void)pictureSelected { NSLog(@"Push"); } ! @end
  12. 12. Notification(通知) 仲介役がObserverクラスと、Subjectクラ スのひも付けと連絡を行う。 OK Tapって通知があったら教えてね Observer クラス Subject クラス NSnotificationCenter addObserver 通知があったら、これを コールバックしてね Observer クラス !! Tapって通知を送る NSnotificationCenter postNotification Subject クラス 通知あった Tapって通知をあったよ!! Observer クラス NSnotificationCenter コールバック Subject クラス
  13. 13. Notification実装 (NotificationCenterにObserber登録) NSNotificationCenterを取得する。 Observerを登録する。知らせて欲しい通知と、知らせ る際に呼び出してもらうセレクターを指定する。(この 娘の返事だけ、教えてねということもできます。)
  14. 14. // // // Screen1ViewController.m ! #import "Screen1ViewController.h" #import "PictureView.h" ! @interface Screen1ViewController () ! @end ! @implementation Screen1ViewController ! - (id)init { self = [super init]; if (self) { // Custom initialization self.title = @"Album"; self.view.backgroundColor = [UIColor grayColor]; // NSNotificationCenterを取得する NSNotificationCenter* center; center = [NSNotificationCenter defaultCenter]; // Observerとして登録する [center addObserver:self selector:@selector(pictureSelected:) name:@"PictureTaped" object:nil]; } return self; }
  15. 15. Notification実装 (通知を送る) NSNotificationCenterを取得する。 送る通知(NSNotification)を作成する。 NSNotificationCenterに、通知を送る。
  16. 16. // // // PictureView.m ! #import "PictureView.h" ! @implementation PictureView ! - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.userInteractionEnabled = YES; } return self; } ! - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // NSNotificationを作成する NSNotification* notification; notification = [NSNotification notificationWithName:@"PictureTaped" object:self userInfo:nil]; // NSNotificationCenterを取得する NSNotificationCenter* center; center = [NSNotificationCenter defaultCenter]; // 通知を行う [center postNotification:notification]; } ! @end // // // PictureViewDelegate.h ! #import <Foundation/Foundation.h> ! @protocol PictureViewDelegate <NSObject> @optional -(void)pictureSelected:(NSNotification *)notification; ! @end
  17. 17. Notification実装 (通知を受け取る) コールバックされてくるメソッドで、通知 (NSNotification)を受け取る。 NSNotificationに含まれる情報、 UserInfo(NSDictionary)の中身をもとに必要な 処理を行う。
  18. 18. // // // Screen1ViewController.m ! #import "Screen1ViewController.h" #import "PictureView.h" ! @interface Screen1ViewController () ! @end ! @implementation Screen1ViewController ! - (id)init { self = [super init]; if (self) { // Custom initialization self.title = @"Album"; self.view.backgroundColor = [UIColor grayColor]; // NSNotificationCenterを取得する NSNotificationCenter* center; center = [NSNotificationCenter defaultCenter]; // Observerとして登録する [center addObserver:self selector:@selector(pictureSelected:) name:@"PictureTaped" object:nil]; } return self; } ! - (void)viewDidLoad { [super viewDidLoad]; UIImage* image01 = [UIImage imageNamed:@"picture01.jpeg"]; PictureView* uiImageView1 = [[PictureView alloc] initWithFrame:CGRectMake(10, 10, 100, 150)]; uiImageView1.image = image01; uiImageView1.tag = 1; [self.view addSubview:uiImageView1]; ! UIImage* image02 = [UIImage imageNamed:@"picture02.jpeg"]; PictureView* uiImageView2 = [[PictureView alloc] initWithFrame:CGRectMake(120, 10, 100, 150)]; uiImageView2.image = image02; uiImageView2.tag = 2; [self.view addSubview:uiImageView2]; } ! -(void)pictureSelected:(NSNotification*)notification { NSLog(@"Push %@",notification.userInfo); } ! @end
  19. 19. KVO(キー値監視) キー値監視とは、ほかのオブジェクトに属する特定の プロパティの変化について通知をオブジェクトが受け 取れるようにする仕組みです。(キー値監視に必要な メソッドは、ルートクラスであるNSObjectに実装さ れている。)
  20. 20. KVO実装 (Subjectクラス) 監視する値を持つクラスを作成する。 // // // KVOclass.h ! #import <Foundation/Foundation.h> ! @interface KVOclass : NSObject { int value_; } @property int value; ! @end // // // KVOclass.m ! #import "KVOclass.h" ! @implementation KVOclass @synthesize value = value_; ! @end
  21. 21. KVO実装 (Subjectクラス) Subjectクラスにオブザーバーを追加する。 OBserverクラスに、変更通知を受け取るメソッド を、オーバーライドする。
  22. 22. // // // Screen1ViewController.m ! #import "Screen1ViewController.h" #import "KVOclass.h" @interface Screen1ViewController () ! @end ! @implementation Screen1ViewController ! - (id)init { self = [super init]; if (self) { // Custom initialization self.title = @"KVO Test"; self.view.backgroundColor = [UIColor grayColor]; } return self; } ! - (void)viewDidLoad { [super viewDidLoad]; ! ! KVOclass* kvo01 = [KVOclass new]; [kvo01 addObserver:self forKeyPath:@"value" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil]; KVOclass* kvo02 = [KVOclass new]; [kvo02 addObserver:self forKeyPath:@"value" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:nil]; kvo01.value = 1; // 値を変更 } ! - (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { if ([keyPath isEqual:@"value"]) { NSLog(@"New Key = %@",[change objectForKey:NSKeyValueChangeNewKey]); } } ! @end

×