Object-c block原理

一,介绍

  block是c语言的语法,以及运行时的一个特性,非常像c中的标准函数,但它运行需要编译器和运行时支持。

  从Mac os 10.6以及ios4以来,apple引入了Blocks的新概念。Blocks有点像函数,但是它可以在其他函数中进行声明和定义。它具有闭包特性,是匿名函数,可以捕获其所在作用域中的变量。


二,语法

1,block的声明格式:

返回值类型(^block的名字)(参数类型1,参数类型2,.......)

2,block的定义格式:

^返回值类型(参数类型1 参数名,参数类型2 参数名.......){return 返回值类型;}

如:void(^myBlock)(int a);

typedef void(^blockType)(int a);//声明block类型为blockType

blockType myblock;//声明blcok变量 myblock

myblock = ^(int a){return a*a};//变量myblock赋值

myblock(2);//block调用

注:返回值类型是可以省略的

如:int (^add) (int,int) = ^(int number1,int number2){return number1+number2;}




typedef void (^blockType)(void)

- (void)method:(id)obj block:(blockType)block 或者

- (void)method:(id)obj block:(void(^)(void))block  (参考UIView animation block)

[ obj method:obj block:^(void){ stat1;stat2; } ] (这里就是上面提到的匿名block


三,基本用法

1,add(2,3);//输出5

2,Block在oc中也是一个对象,可以对其进行release,copy,retain等操作。

  如[add copy];

3,闭包特性

void testBlock(){

int a =1;

int b = 3;

int(^sum)(void) = ^{

return a + b;

};

printf(@"%d",sum);//输出是4;

a = 2;

printf(@"%d",sum);//输出仍是4;

};

原因:a和b都是自由变量或者local变量,在block中是只读的。在定义sum的时候,编译器已经对a和b做了一个const拷贝,不能在sum中修改a的值并保存。


4,如果想在block中修改外部自由(local)变量,一是可以引用_block修饰,二是可以用static改成全局变量。这时自由变量是可写的

void testBlock(){

_block int a =1;

int b = 3;

int(^sum)(void) = ^{

return a + b;

};

printf(@"%d",sum);//输出是4;

a = 2;

printf(@"%d",sum);//输出仍是4;

};


四,blocks的应用

1,用作多线程的代码单元(GCD),多核并行编程。

2,用作某个函数调用完成后的回调函数。如UIView动画,Notification。

  Block作为回调函数比传统回调函数的优越性:

   在函数调用的时候,将block作为一个参数传递,使得代码紧凑,结构清晰。

例如:

block之前,

  • - (void)viewDidLoad {
  •    [super viewDidLoad];
  •     [[NSNotificationCenter defaultCenter] addObserver:self
  •         selector:@selector(keyboardWillShow:)
  •         name:UIKeyboardWillShowNotification object:nil];
  • }
  •  
  • - (void)keyboardWillShow:(NSNotification *)notification {
  •     // Notification-handling code goes here.
  • }
block之后,

  • - (void)viewDidLoad {
  •     [super viewDidLoad];
  •     [[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification
  •          object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
  •              // Notification-handling code goes here. 
  •     }];
  • }
3,允许访问本地变量,这样可以避免通过结构体将本地变量封装后传递给回调函数。最为典型的就是异步数据下载后,更新ui。

NSString* parameter = [self getSomeParameter];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{NSString* result = [self fetchResultFromWebWithParameter:parameter]; 

dispatch_async(dispatch_get_main_queue(), ^{[self updateUIWithResult:result]; // 能直接使用上层block中的变量result,只读的。所以说可以直接使用局部变量});

});


五,Blocks的内存管理

 上面提到,block是分配在栈上的,它也可以跟其他的对象一样retain,release;有时,我们需要延长block的生命周期,可以使用Block_copy(block)将block变量拷贝到heap上


  

[block1 copy] 后,原先分配在stack上的__block 变量 shared 别移动了heap上;


对于copy到heap中的block 再copy时,行为同普通对象retain一样,会使引用计数+1


六,oc编程,简单的代码示例

//遍历数组

+ (NSArray *)retrieveInventoryItems{

    NSMutableArray *inventory = [NSMutableArraynew];

    NSError *err = nil;

    NSArray *jsonInventory = [NSJSONSerializationJSONObjectWithData:[NSDatadataWithContentsOfFile:[NSURLURLWithString:kInventoryAddress]]options:kNilOptionserror:&err];

    [jsonInventory enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop){

        NSDictionary *item = obj;

        [inventory addObject:[[IODItemalloc]initWithName:[item objectForKey:@"Name"]andPrice:[[itemobjectForKey:@"Price"]floatValue]andPictureFile:[item objectForKey:@"Image"]]];

       

    }];

    //不直接返回inventory,因为我们要的是一个不可变的数组。copy创建的是一个不可变的数组,所以我们可以大胆返回它。

     return [inventory copy];

}

//在main queue上添加其他queue

dispatch_async(queue, ^{

        self.inventory = [[IODItemretrieveInventoryItems]mutableCopy];

        dispatch_async(dispatch_get_main_queue(), ^{

        ibChalkboardLabel.text =@"Inventory LoadednnHow can I help you?";

        

        });

    

    });

//常用的动画显示

 [UIView animateWithDuration:1.0
                     animations:^{
                         [removeItemDisplay setCenter:[ibCurrentItemImageView center]];
                         [removeItemDisplay setAlpha:0.0];
                     } completion:^(BOOL finished) {
                         [removeItemDisplay removeFromSuperview];
                     }];

具体了解,还是看apple文档    地址https://developer.apple.com/library/ios/featuredarticles/Short_Practical_Guide_Blocks/index.html


block原理介绍 推荐 http://blog.csdn.net/jasonblog/article/details/7756763


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值