OC语言(七)Block复习

看下面一道Block的面试题:

int i = 10;
void(^myBlock)() = ^{
    NSLog(@"%d",i);
};
i = 100;
myBlock();

经过这个过程后,输出的i应该是10而不是100,在定义block时会将block前面的局部变量进行拷贝,后续的变量改变不会影响block内部的拷贝变量值,如果要操作block中变量的值,应该加上__block关键字。


另外一道:

Tip:如果在block中使用了self,block会对self强引用。

@property (nonatomic, strong) NSMutableArray *myBlocks;

int(^sum)(int,int) = ^(int x, int y){
   return [self sum:x y:y];
}
[self.myBlocks addObject:sum];

注意到self对myBlocks是强引用,如果把sum加入到myBlocks数组中,myBlocks数组又会有强指针指向sum,由于sum这个block需要调用self的方法,因此sum对self是强引用,因此构成了循环引用,无法释放。


第三道:

如果self对象持有操作对象(例如类直接有block),而操作对象(如block)又直接访问了self,则block会对self构成强引用,self又对block强引用,会造成循环引用。

单纯在操作对象(如block)中操作self不会造成循环引用

例如使用线程创建block,由于非主线程默认没有消息循环(Run Loop),因此线程销毁时block也会销毁,block为线程所有,不是self所有,不会造成循环引用。

@interface DemoObj ()

@property (nonatomic, strong) NSOperationQueue *queue;

@end

@implementation DemoObj

- (instancetype)init{
    
    if(self = [super init]){
        self.queue = [[NSOperationQueue alloc] init];
    }
    
    return self;
    
}
- (void)dealloc{
    
    NSLog(@"dealloc successfully");
    
}

- (void)demoOp:(id)obj{
    
    NSLog(@"%@ %@",[NSThread currentThread],obj);
    
}

- (void)demoBlockOp{
    [self.queue addOperationWithBlock:^{
        [self demoOp:@"hello"];
    }];
}
这种情况下,self对queue强引用,queue对block强引用,虽然block对self也有强引用,但是线程消失时block会销毁,也就不存在引用环了,因此self只有直接拥有block时才会造成循环引用。
Tip:在这种情况下,不能使用self的弱引用(__weak Demoobj *weakself = self),这样对象会在创建时的强指针销毁时被销毁,也就是说block指向的self类不能保证其存在,故block会无法调用self,注意不能使用弱引用!!!


原文地址:https://www.cnblogs.com/aiwz/p/6154196.html