NSInvocationOperation,delegatePattern

Lecture12迄の内容を基に"Presence"アプリケーションを拡張していきます。 AssignmentPresence3になります。
CS193P - Cocoa Programming | Announcements.jpg
iPhone Application Programming

今迄、作成したソースはhttp://public.me.com/seijit/iPhone/CS193Pから

今回の目標

前回迄は全てMainThreadで通信を行っていました。その為、待ち時間が長く感じられ、ストレスを受けていたのではないかと思います。今回はそのストレスを軽減する為に別Threadで通信を行い、最後にMainThreadの処理を返すように実装を行います。アプリケーションとしては下の図のように自分のStatusをUpdateする画面を用意し、そこからSendできるようにします。

Presence-Part3-1-1.jpg

今回は全てを記述するのは大変なので、要点を絞って記載します。

picture.pngNSInvocationOperationの作成

ViewがLoadされる際にSelector(synchronousLoadsTwitterUsers)を指定してNSInvocationOperationを作成し、それをNSInvocationOperationQueueにAddします。その中で通信部分の処理を行っています。

また、作成時に指定したSelector内部ではSelector(didFinishLoadingTwitterUsersWithResults)を指定してMainThreadに返しています。

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
	if ([myData count] == 0) {
		[self showLoadingIndicators];
		[self beginLoadingTwitterUsers];
	}
}
- (void)beginLoadingTwitterUsers {
	[myData removeAllObjects];

	NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(synchronousLoadsTwitterUsers) object:nil];
	[operationQueue addOperation:operation];
	[operation release];
}
- (void)synchronousLoadsTwitterUsers {
	NSBundle *bundle = [NSBundle mainBundle];
	NSArray *twitterUsers = [NSArray arrayWithContentsOfFile:[bundle pathForResource:@"TwitterUsers" ofType:@"plist"]];

	for (NSString *userName in twitterUsers){
		Person *person = [[Person alloc] initWithPersonName:userName];
		if (person)
			[myData addObject:person];
		[person release];
	}
	[self performSelectorOnMainThread:@selector(didFinishLoadingTwitterUsersWithResults) withObject:nil waitUntilDone:NO];
}
- (void)didFinishLoadingTwitterUsersWithResults {
	[self hideLoadingIndicators];
	[self.tableView reloadData];
    [self.tableView flashScrollIndicators];
}

picture.pngdelegete Patternの使用

NavigationItemのRightBarButtonItemをクリックするとStatusComposeする画面をModallyに出すようにしています。


- (void)viewDidLoad {
    [super viewDidLoad];
	UIBarButtonItem *addButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(presentModally) ];
	self.navigationItem.rightBarButtonItem = addButton;
	[addButton release];
}
- (void)presentModally {
	StatusComposeViewController *statusController = [[StatusComposeViewController alloc]initWithNibName:@"StatusCompose" bundle:nil];
	statusController.delegate = self;
	[self presentModalViewController:statusController animated:YES];
	[statusController release];
}

この場合、このActionは今回で言うとPersonListViewControllerに実装するわけです。ではこの画面を消すActionはどこに書けばいいのでしょうか?

単純にStatusComposeViewControllerに下のように実装しても消すことはできます。


[self.navigationController dismissModalViewControllerAnimated:YES];

しかし、PresentとDismissするのは同じContorollerからするのが望ましいと言われています。別の操作を行うのにもこの方が操作をしやすいでしょう。

ここでdelegatePatternを使用します。

Protocolの作成

@class StatusComposeViewController;

@protocol StatusComposeViewDelegate 
@optional
- (void)statusComposeViewControllerDidFinish:(StatusComposeViewController *)controller;
- (void)statusComposeViewControllerDidCancel:(StatusComposeViewController *)controller;
@end

今回のdelegateの為のProtocolを作成します。

Propertyの追加


@interface StatusComposeViewController : UIViewController  {
	// 略
	id  delegate;
}
	// 略
@property (nonatomic, assign) id  delegate;
	// 略
@end

StatusComposeViewControllerにStatusComposeViewDelegateを満たしたid型の属性を追加します。

StatusComposeViewDelegateの実装

StatusComposeViewDelegateのメソッド(statusComposeViewControllerDidFinish:, statusComposeViewControllerDidCancel: )を実装します。

これでStatusComposeViewController側でStatusComposeViewDelegateで実装されたPersonListViewControllerのメソッド(i.e [self.delegate statusComposeViewControllerDidFinish:])を呼べばよいわけです。

これでAssignmentPresence3を終了としたいと思います。

今回作成したソースはhttp://public.me.com/seijit/iPhone/CS193P/Lecture12のPresence5.tar.gzです

No comments yet.

Leave a comment

This is the comment form.

Recent Entry

Related posts