OC 语法Blcok(代码块,闭包)的使用和注意

引言:


Block是Apple在iOS4.0对Objective-C引入的新特性,通过Block可以增强代码的可读性和耦合性,减少非必要性的代理(Delegate)模式.

Block是一个代码块,非常类似JavaScript里面的匿名函数,也可以叫做闭包,所以你也可以用匿名函数的方式来理解Block.

本文Block的运行环境是在ARC模式下进行,非ARC的Block内存管理方面还是较为繁琐.所以,有了ARC,开发者不必过多的去关注Block在内存支配方面的问题.


使用:

第一种

是局部变量(某个方法内使用):

方法内辅助输入 inlineBlock

<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
    <#statements#>
};
void(^print)(int a) = ^(int a) {
        NSLog(@"%d", a);
    };

第二种

是通过typedef来定义一个新的Block, 这样声明在头文件中, 引用就可以在其他类中重复使用

方法外辅助输入:typedefBlock

typedef <#returnType#>(^<#name#>)(<#arguments#>);
typedef void(^TypeDefBlockType)(int a)

第三种

类的成员变量是blcok类型

两种方式声明成员变量

@property (nonatomic, copy) TypeDefBlcokType chooseBlcok;

@property (nonatomic, copy) void(^chooseBlcok)(NSDictionary *);

第四种

方法参数是block类型

两种方式设置block方法


- (void)setChooseBlock:(TypeDefBlcokType)chooseBlock{
}

- (void)setChooseBlock:(void (^)(int a))chooseBlock{
}

注意

注意点1:

使用Block最大的一个好处就是可以在代码块中随时访问外部变量,比如你在A.class类中的某个方法中声明了一段代码块.

你可以在代码块中直接对A.class所拥有的成员变量进行调用,并且,通过一定的条件(__block),还可以随时的修改这些变量的值和指针.

下面看一段代码的实例:

- (void)testBlock {
    int count = 0;
    __block int count2 = 0;
    
    void(^print)(int a) = ^(int a) {
        count ++;//报错.没有用__block修饰的局部变量不能访问
        count2 ++;
        NSLog(@"%d", a);
    };
    
    print(1);
}

1:通过图中可以看到,对没有通过__block修饰的局部变量进行赋值会修改指针地址,编译器会产生警告,提示这是无效的编码,正确的方式是为局部变量加上__block修饰.

2:在Block里面可以随时访问全局变量,静态变量等,并对它们的值和指针进行修改.

3:但在Block中直接使用所在声明区域的类的成员变量和self时也是可以直接使用和修改的,但需要注意循环引用.

注意点2:

开启ARC以后,Block的内存管理也交给了ARC,这让开发者不用再去关心何时需要引用,何时需要释放.如果要释放某个不再需要使用的Block成员变量,只需要将其设置nil即可.

但在这强大的环境下,我们的编码也任然需要谨慎,否则很容易产生循环引用.

在编码过程中,编译器可能会产生像下面这样的警告:

例如引用self要使用

__weak KSViewController * wself = self;   
_observer = [[NSNotificationCenter defaultCenter]   
             addObserverForName:@"TestNotificationKey"   
             object:nil queue:nil usingBlock:^(NSNotification *n) {   
                 KSViewController * sself = wself;   
                 if (sself) {   
                     NSLog(@"%@", sself);   
                 }   
                 else {   
                     NSLog(@"<self> dealloc before we could run this code.");   
                 }   
             }];   

在 block 之前定义对 self 的一个弱引用 wself,因为是弱引用,所以当 self 被释放时 wself 会变为 nil;然后在 block 中引用该弱应用,考虑到多线程情况,通过使用强引用 sself 来引用该弱引用,这时如果 self 不为 nil 就会 retain self,以防止在后面的 使用过程中 self 被释放;然后在之后的 block 块中使用该强引用 sself,注意在使用前要对 sself 进行了 nil 检测,因为多线程环境下在用弱引用 wself 对强引用 sself 赋值时,弱引用 wself 可能已经为 nil 了。 通过这种手法,block 就不会持有 self 的引用,从而打破了循环引用。


其他资料:

iOS中block实现的探究

转载于:https://my.oschina.net/bieshixuan/blog/1523019

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值