2010年10月15日金曜日

「Cocoa Notification (NSNotification,NSNotificationCenter)」と「キー値監視」(2)

「Cocoa Notification (NSNotification,NSNotificationCenter)」を実際に試してみることにする。

新規プロジェクトをView-based Applicationを選択して名前をMyNotificationとして作成してます。

新規ファイル追加で、NSObjectを継承したMyNotificationを作成しています。

以下、編集したファイルの中身です。
なるべく簡潔に分かりやすくを心がけたつもり。



// MyNotificationViewController.h

#import <UIKit/UIKit.h>

@interface MyNotificationViewController : UIViewController {
}

@end



// MyNotificationViewController.m

#import "MyNotificationViewController.h"
#import "MyNotification.h"

@implementation MyNotificationViewController

/*
* 通知受け取ったときに呼ばれる処理
*/
- (void)owatayo
{
NSLog(@"メインスレッド:通知owataを受け取ってowatayoメソッドを実行したよ。");
}

- (void)viewDidLoad
{
[super viewDidLoad];

NSLog(@"メインスレッド:処理開始");

// ここでは、通知を受けるObserverをselfとし、通知するSubjectをmyNotificationとする。
// 新しいスレッドをたて、その新スレッドからの通知を受け取れることの確認によって「監視」のテストとする。
MyNotification *myNotification = [[[MyNotification alloc] init] autorelease];

// NSNotificationCenterのインスタンスに、
// addObserver : 通知を受け取るオブジェクト(ここでは自分自身)
// selector : 通知を受けたときに実行するメソッド
// name : 通知される通知名
// object : どのオブジェクトからの通知を受け取るのか指定できる。nilであれば限定しない。
NSNotificationCenter *center;
center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(owatayo) name:@"owata" object:myNotification];

// 新しいスレッドをたて、myNotificationのmyWorkメソッドを実行する。
[NSThread detachNewThreadSelector:@selector(myWork) toTarget:myNotification withObject:nil];

NSLog(@"メインスレッド:処理終了");
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
}

- (void)dealloc {
[super dealloc];
}

@end




// MyNotification.h

#import <Foundation/Foundation.h>

@interface MyNotification : NSObject {
}

- (void)myWork;
- (void)didMyWork;

@end



// MyNotification.m

#import "MyNotification.h"

@implementation MyNotification

/*
* 新スレッドでの処理
*/
- (void)myWork
{
NSLog(@"新スレッド:処理開始");
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];

for (int i=0; i<5; i++) {
[NSThread sleepForTimeInterval:1.0];
NSLog(@"新スレッド:%d", i);
}

[self didMyWork];
[pool release];
NSLog(@"新スレッド:処理終了");
[NSThread exit];
}

/*
* 新スレッド終了するときの通知させる処理
*/
- (void)didMyWork
{
// 通知を受け取る側では以下のようにobserverをNSNotificationCenterに追加している。
// NSNotificationCenter *center;
// center = [NSNotificationCenter defaultCenter];
//[center addObserver:self selector:@selector(owatayo) name:@"owata" object:myNotification];
//
// name:@"owata" と notificationWithName:@"owata" で指定している @"owata" をキーとして通知のやりとりを行う。
// 後は、NSNotification の postNotification: で通知を送れば、勝手に通知を受け取ってくれる。
NSNotification *notification;
notification = [NSNotification notificationWithName:@"owata" object:self userInfo:nil];

NSLog(@"新スレッド:通知を送るよ。通知の名前はowataだよ。");
NSNotificationCenter *center;
center = [NSNotificationCenter defaultCenter];
[center postNotification:notification];
}

@end

こんな感じにログがでるはず。

2010-10-15 18:51:43.333 MyNotification[2310:207] メインスレッド:処理開始
2010-10-15 18:51:43.336 MyNotification[2310:5c03] 新スレッド:処理開始
2010-10-15 18:51:43.336 MyNotification[2310:207] メインスレッド:処理終了
2010-10-15 18:51:44.337 MyNotification[2310:5c03] 新スレッド:0
2010-10-15 18:51:45.338 MyNotification[2310:5c03] 新スレッド:1
2010-10-15 18:51:46.339 MyNotification[2310:5c03] 新スレッド:2
2010-10-15 18:51:47.341 MyNotification[2310:5c03] 新スレッド:3
2010-10-15 18:51:48.342 MyNotification[2310:5c03] 新スレッド:4
2010-10-15 18:51:48.343 MyNotification[2310:5c03] 新スレッド:通知を送るよ。通知の名前はowataだよ。
2010-10-15 18:51:48.344 MyNotification[2310:5c03] メインスレッド:通知owataを受け取ってowatayoメソッドを実行したよ。
2010-10-15 18:51:48.345 MyNotification[2310:5c03] 新スレッド:処理終了


追記:赤文字の部分にちょっと注意が必要そうなので、次の記事でそのこと書く。今回書いたサンプルコードではスレッド・セーフになってなさそう。

あれ?もしかして、NSNotification と NSNotificationCenter 使うと超簡単だったりするんじゃないの?

続く。

0 件のコメント:

コメントを投稿