Objective C对象之间信息传递(二)block

http://www.ohcoder.com/post/2012-03-30/17527323

上篇文章,总结了Objective C的对象之间使用协议(protocol)传递消息的方式,本次和大家分享另外一种方式,即使用块(block)实现对象之间信息的传递。

首先简单说明一下什么是block?

其实,block是和函数类似的代码块儿,下面举个定义block的例子,一目了然。

^(参数列表..){

代码块..

};

接下来是block pointer,所谓的块指针,很像C++中的函数指针哦!

返回值(^名称)(参数列表...);

那么对这个块指针进行附值就可以写成这样,

名称 = ^(参数列表...){代码块};

以后如果想调用此块,就可以写成这样,

名称(参数列表...);

其次,如果想在块(block)中修改变量,需要在变量前面添加__blcok关键字(注意block前面的下划线是两个短线哦) ,添加这个关键字的目的是为了明确说明此变量为block variable。

有人可能会有疑问为什么要添加__blcok关键字呢?这可能和Apple的新特性GCD(Grand Central Dispatch,针对多核进行并行计算的特性,更多看这里)有很大关系吧,此处就不多说了,有兴趣的同学可以找找相关资料。

下面给出一个小例子,供大家学习参考,这个例子和上一篇中的例子基本一样,只不过少了协议(protocol),只剩下Dog类和Person类。

  • Dog类接口

1
2
3
4
5
6
7
8
9
10
11
12
13
#import<Foundation/Foundation.h>
typedef int(^MyBlcok)(int a,int b);//这里为其中一个block进行了自定义
@interface Dog :NSObject{
int _ID;
NSTimer *timer;
int barkCount;
void(^BarkCallback)(Dog *thisDog,int count);
MyBlcok simBlcok;//进行了自定义的block
}
@property(assign)int ID;
-(void)SetBark:(void(^)(Dog *thisDog,int count))eachBark;
-(void)GetMyBlcok:(MyBlcok)mb;  //进行了自定义的block
@end
  • Dog类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#import "Dog.h"
@implementation Dog
@synthesize ID =_ID;
-(id)init{
self = [super init];
if (self) {
timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self
                            selector:@selector(UpdateTimer:)
                            userInfo:nilrepeats:YES];
  }
return self;
}
-(void)SetBark:(void(^)(Dog *,int))eachBark{
if (BarkCallback != eachBark) {
    [BarkCallback release];
  }
BarkCallback = [eachBar copy]; //注意:这里对block进行了copy操作
}
-(void)GetMyBlcok:(MyBlcok)mb{
if (simBlcok != mb) {
    [simBlcok release];
  }
simBlcok = [mb copy]; //注意:这里对block进行了copy操作
}
-(void)UpdateTimer:(id)arg{
barkCount++;
NSLog(@"dog %d bark count %d",_ID,barkCount);
if(BarkCallback) {
    BarkCallback(self,barkCount);     //这里调用了block
}
if(simBlcok) {
    int num =simBlcok(5,barkCount);    //这里调用了block
    NSLog(@"simBlock num is %d", num);
  }
}
-(void)dealloc{
[simBlcok release];     //注意:这里对block进行了释放
[BarkCallback release]; //因为block执行了copy操作,需要手动删除
[super dealloc];
}
@end
  • Person类接口

1
2
3
4
5
6
7
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person :NSObject{
Dog *_dog;
}
@property(retain)Dog *dog;
@end
  • Person类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#import "Person.h"
@implementation Person
@synthesize dog = _dog;
-(void)setDog:(Dog *)dog{
if(_dog != dog){
   [_dog release];
   _dog = [dog retain];
}
[_dogSetBark:^(Dog *thisDog,int count) {
NSLog(@"person dog: %d count:%d", [thisDog ID], count);
  }];
[_dog GetMyBlcok:^int(int a,int b){
   NSLog(@"MyBlock is going on.numA:%d;numB:%d", a, b);
   return (a+b);
  }];
[_dog GetMyBlcok:^int(int a,int b) {
   return 1;
  }];
}
-(Dog*)dog{
return _dog;
}
-(void)dealloc{
[_dog release];
[super dealloc];
}
@end
  • Main方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <Foundation/Foundation.h>
#import "Dog.h"
#import "Person.h"
int main(int argc,const char * argv[])
{
@autoreleasepool{
   Person *xiaoLi = [[Person alloc]init];
   Dog *dog = [[Dog alloc]init];
   [dog setID:10];
   [xiaoLi setDog:dog];
   [dog release];
   while (1) {
       [[NSRunLoop currentRunLoop]run]; //为了保持主循环不中断
   }
   [xiaoLi release];
}
return 0;
}

上面是一个使用block的小例子,其中涉及到如何定义以及如何调用。其中需要注意的是,block初始生成的时候是放在堆里的,当使用copy方法后,就会在栈里生成相应的block,此时就需要进行手动删除,当然了,这次是在非ARC模式下编写的,如果在ARC模式下编写应该就没有这个顾虑,之所以在非ARC下展示,其实也是为了说明这里有一点点不一样的地方。

这样,通过协议(protocol)和块(block)就可以实现对象之间的消息传递。

其实,一般情况下使用块(block)可能更简洁一些,使用协议(protocol)的原因可能是有更多其它考虑,具体使用哪个都是可以的,关键还是看需求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值