__block与__weak的区别

注:查看资料,自己总结

1,什么时候用__block?
首先要知道,Block可以访问局部变量,但是不能修改
如果修改局部变量,需要加__block
(全局变量除外,系统默认会自动带上__block修饰)

__block int multiplier = 7;
 int (^myBlock)(int) = ^(int num) {
 multiplier ++;  //这样就可以了,如果multiplier没有被__block修饰的话,会报错 
return num * multiplier; };

2,什么时候用__weak?
当block代码块中出现循环引用时候,会用__weak修饰,一般多用于修饰self当前对象

__weak __typeof(&*self)weakSelf =self; //等同于
//__weak UIViewController *weakSelf =self;

self.blockname = ^(NSString *name){

self.name = name;//如果self没有被修饰的话,会出现循环引用
//(因为self引用了block,block里面又引用了self)
//为什么不用__block?
//是因为通过引用来访问self的实例变量 ,self被retain,block也是一个强引用,引起循环引用,用__week是弱引用,当self释放时,weakSelf已经等于nil。
}

补充:
如果局部变量是数组或者指针的时候只复制这个指针,两个指针指向同一个地址,block只修改指针上的内容。如:

NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@"a",@"b",@"abc",nil];
 NSMutableArray *mArrayCount = [NSMutableArray arrayWithCapacity:1];
 [mArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock: ^(id obj,NSUInteger idx, BOOL *stop){

 [mArrayCount addObject:[NSNumber numberWithInt:[obj length]]];
 }];
 NSLog(@"%@",mArrayCount);

例子里面确实没有修改mArrayCount这个局部变量啊。
mArrayCount是一个指针,指向一个可变长度的数组。
在block里面,并没有修改这个指针,而是修改了这个指针指向的数组。
换句话说,mArrayCount是一个整数,保存的是一块内存区域的地址,
在block里,并没有改变这个地址,而是读取出这个地址,然后去操作这块地址空间的内容。
这是允许的,因为声明block的时候实际上是把当时的临时变量又复制了一份,在block里即使修改了这些复制的变量,也不影响外面的原始变量。即所谓的闭包。
但是当变量是一个指针的时候,block里只是复制了一份这个指针,两个指针指向同一个地址。所以,在block里面对指针指向内容做的修改,在block外面也一样生效。

注意:在垃圾回收机制里面,如果你同时使用__weak和__block来标识一个变量,那么该block将不会保证它是一直是有效的。 如果你在实现方法的时候使用了block,对象的内存管理规则更微妙:也是(__weak与__block区别:)
1、如果你通过引用来访问一个实例变量,self会被retain
2、如果你通过值来访问一个实例变量,那么变量会被retain

你可能感兴趣的:(__block与__weak的区别)