Presentation



Presentation

0 0


Presentation


On Github Sean8694 / Presentation

Communication Patterns

消息传递机制

几种消息传递机制

  • Delegate
  • Notification
  • Block
  • Target-Action
  • KVO

Delegate特点(1)

发送者只需要知道接收者符合一定的协议,所以两者结合很松

也许发送者只知道接收者接口
例: 使用UIScrollViewDelegate监听UIScrollView滚动状态
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;


往往,我们使接收者也知道发送者
例: UITableView作为UIViewController的成员属性,以便于配置数据及操作
self.tableView.delegate = self;

关键在于: 缺少容器

sender.delegate = receiver;
谁实现了这句话,谁就"知道的太多了"...
不利于消息"远距离传输"

Delegate特点(2)

1对1

Delegate特点(3)

方法名可以描述功能,传递参数明确,语义清晰

UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;

Delegate特点(4)

可以有返回参数,给发送者做出回应

UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

Delegate小结

  • 确保发送者和接收者可以独立工作,否则会有风险。
  • 发送者只需要知道接收者符合一定的协议。
  • 发送者与接收者是一一对应的。
  • 发送内容及参数明确,语义清晰。
  • 可以有返回值给发送者,作为回应。
  • 两者不宜相隔很远的模块之间消息传递。
  • 结构松散,两者耦合度比较低。

Notification特点(1)

标准的观察者模式,发送者根本不知道接收者两者可以相隔非常远

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;
... ...

https://gist.github.com/hpique/7554209

Notification特点(2)

一个发送者对应多个接收者 《Head First设计模式》

Notification特点(3)

触发事件靠字符串描述,传递参数不明确无法返回参数告知消息发送者

UIKIT_EXTERN NSString *const UIKeyboardWillShowNotification;
UIKIT_EXTERN NSString *const UIKeyboardDidShowNotification; 
UIKIT_EXTERN NSString *const UIKeyboardWillHideNotification; 
UIKIT_EXTERN NSString *const UIKeyboardDidHideNotification;

Notification小结

  • 标准的观察者模式,发送者根本不知道接收者
  • 一个发送者对应多个接收者
  • 触发事件靠字符串描述,传递参数不明确
  • 无法返回参数告知消息发送者
  • 两者可以相隔非常远
  • 结构非常松散,两者耦合度低

Block特点(1)

通常可以替代Delegate消息传递方式,比使用Delegate更加方便但是容易产生循环引用

self.myTableView.selectionHandler = ^void(NSIndexPath *selectedIndexPath) {
    // 处理选择
};

self->tableView->handler-?>self

Block特点(1)续

处理不当可能会循环引用

self.queue = [[NSOperationQueue alloc] init];
MyOperation *operation = [[MyOperation alloc] init];
operation.completionBlock = ^{
    [self finishedOperation];
};
[self.queue addOperation:operation];

必须要记得将operation从queue中移除。

Block特点(2)

代码实现的位置会更易理解

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);
}];

Block小结

  • 比使用Delegate更加方便
  • 容易产生循环引用
  • 代码实现的位置会更易理解

Target-Action特点(1)

Target-Action 是回应 UI 事件时典型的消息传递方式

[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething)];

消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么

Target-Action特点(2)

如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象

Target-Action小结

  • 一般不会用
  • UI 事件时典型的消息传递方式
  • 消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么
  • 如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象

KVO特点(1)

KVO 是提供对象属性被改变时的通知的机制

[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSomething)];

消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么

Target-Action特点(2)

如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象

Target-Action小结

  • 一般不会用
  • UI 事件时典型的消息传递方式
  • 消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么
  • 如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象

做出正确的选择

流程图的建议不代表最终答案

做出正确的选择

Table view 的 delegate

做出正确的选择

Core Data 使用 notification 传递事件

做出正确的选择

-[NSURLSession dataTaskWithURL:completionHandler:] 来作为一个 block API

做出正确的选择

target-action 是 UI 中消息传递的最佳选择

做出正确的选择

NSOperationQueue 用了 KVO 观察队列中的 operation 状态属性的改变情况

谢谢