在两个类之间进行消息传递,一般通过代理或者block进行,代理写起来较为麻烦,block较为简单,可是block须要特别注意内存泄漏问题,注意self和block之间要为弱引用,以下介绍使用block进行消息传递的方法。
先来复习一下block的结构:
返回类型 (^block名称)(參数1类型,參数2类型...)
以下以XMPP的用户登录为例来说明block消息传递方法。
网络操作在AppDelegate中进行,而登录界面视图控制器类中。由于登录button点击之后须要在授权完毕时让网络操作类通知登录界面,因此在AppDelegate中定义一个block,而且把它作为登录方法的參数。在登录控制器点击了登录button时。必定会调用登录方法,由于登录方法有一个參数是block,因此能够通过这个block实现登录成功后的业务。
而AppDelegate仅仅须要在登录方法被调用时把block存起来,在授权成功后调用block。传递參数就可以。
详细实现例如以下:
①在AppDelegate,也就是须要给还有一个类传递消息的类内,定义一个block和对应的方法:
typedef enum{ XMPPResultTypeSuccess, XMPPResultTypeFailure }XMPPResultType; typedef void (^XMPPResultBlock)(XMPPResultType type);
/** * 用户登录 */ - (void)xmppUserLogin:(XMPPResultBlock)resultBlock;②在视图控制器中实现对应方法,传入一个block:
须要注意的是,由于在block中使用了self,会造成block对self的强引用,这个强引用会使得视图控制器在登录结束后无法销毁,从而造成内存泄漏。因此这里使用一个弱指针来调用控制器的方法。
AppDelegate *app = [UIApplication sharedApplication].delegate; __weak typeof (self) selfVc = self; // 弱引用的控制器 [app xmppUserLogin:^(XMPPResultType type) { [selfVc handleResult:type]; // 注意block引入了一个对控制器的强引用,无法释放当前控制器,因此应当弱引用 }];③在AppDelegate中实现方法时保存传入的block:
@interface AppDelegate () <XMPPStreamDelegate>{ XMPPResultBlock _resultBlock; }
- (void)xmppUserLogin:(XMPPResultBlock)resultBlock{ [self connectToHost]; _resultBlock = resultBlock; }④在授权成功时发送结构,因为block有一个枚举參数。因此能够传入值:
if (_resultBlock) { _resultBlock(XMPPResultTypeSuccess); }因为_resultBlock保存的正是视图控制器传入的block,因此会在调用时实现视图控制器定义的block的内容。