发送者只需要知道接收者符合一定的协议,所以两者结合很松
也许发送者只知道接收者接口 例: 使用UIScrollViewDelegate监听UIScrollView滚动状态 - (void)scrollViewDidScroll:(UIScrollView *)scrollView; 往往,我们使接收者也知道发送者 例: UITableView作为UIViewController的成员属性,以便于配置数据及操作 self.tableView.delegate = self;
关键在于: 缺少容器
sender.delegate = receiver; 谁实现了这句话,谁就"知道的太多了"... 不利于消息"远距离传输"
1对1
方法名可以描述功能,传递参数明确,语义清晰
UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView; - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
可以有返回参数,给发送者做出回应
UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
标准的观察者模式,发送者根本不知道接收者两者可以相隔非常远
UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification; UIKIT_EXTERN NSString *const UIApplicationWillEnterForegroundNotification; UIKIT_EXTERN NSString *const UIApplicationDidFinishLaunchingNotification; UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification; UIKIT_EXTERN NSString *const UIApplicationWillResignActiveNotification; UIKIT_EXTERN NSString *const UIApplicationWillTerminateNotification; ... ...
一个发送者对应多个接收者 《Head First设计模式》
触发事件靠字符串描述,传递参数不明确无法返回参数告知消息发送者
UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification; UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification; UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification; UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification;
通常可以替代Delegate消息传递方式,比使用Delegate更加方便但是容易产生循环引用
self.myTableView.selectionHandler = ^void(NSIndexPath *selectedIndexPath) { // 处理选择 }; self->tableView->handler-?>self
处理不当可能会循环引用
self.queue = [[NSOperationQueue alloc] init]; MyOperation *operation = [[MyOperation alloc] init]; operation.completionBlock = ^{ [self finishedOperation]; }; [self.queue addOperation:operation];
必须要记得将operation从queue中移除。
代码实现的位置会更易理解
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }];
Target-Action 是回应 UI 事件时典型的消息传递方式
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething)];
消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么
如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象
KVO 是提供对象属性被改变时的通知的机制
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething)];
消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么
如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象
流程图的建议不代表最终答案
Table view 的 delegate
Core Data 使用 notification 传递事件
-[NSURLSession dataTaskWithURL:completionHandler:] 来作为一个 block API
target-action 是 UI 中消息传递的最佳选择
NSOperationQueue 用了 KVO 观察队列中的 operation 状态属性的改变情况