Blocks理解:
Blocks可以訪問局部變量是己,但是不能修改
如果修改局部變量又兵,需要加__block
__block int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
multiplier ++;//這樣就可以了
return num * multiplier;
};
2、如果局部變量是數(shù)組或者指針的時(shí)候只復(fù)制這個(gè)指針卒废,兩個(gè)指針指向同一個(gè)地址,block只修改指針上的內(nèi)容沛厨。如:
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);
例子里面確實(shí)沒有修改mArrayCount這個(gè)局部變量啊。mArrayCount是一個(gè)指針摔认,指向一個(gè)可變長度的數(shù)組逆皮。在block里面,并沒有修改這個(gè)指針参袱,而是修改了這個(gè)指針指向的數(shù)組电谣。換句話說,mArrayCount是一個(gè)整數(shù)抹蚀,保存的是一塊內(nèi)存區(qū)域的地址剿牺,在block里,并沒有改變這個(gè)地址环壤,而是讀取出這個(gè)地址晒来,然后去操作這塊地址空間的內(nèi)容。
這是允許的郑现,因?yàn)槁暶鱞lock的時(shí)候?qū)嶋H上是把當(dāng)時(shí)的臨時(shí)變量又復(fù)制了一份湃崩,在block里即使修改了這些復(fù)制的變量,也不影響外面的原始變量接箫。即所謂的閉包攒读。
但是當(dāng)變量是一個(gè)指針的時(shí)候,block里只是復(fù)制了一份這個(gè)指針辛友,兩個(gè)指針指向同一個(gè)地址薄扁。所以,在block里面對(duì)指針指向內(nèi)容做的修改废累,在block外面也一樣生效邓梅。
__weak __typeof(&*self)weakSelf =self; 等同于
__weak UIViewController *weakSelf =self;
為什么不用__block 是因?yàn)橥ㄟ^引用來訪問self的實(shí)例變量 ,self被retain,block也是一個(gè)強(qiáng)引用九默,引起循環(huán)引用震放,用__week是弱引用,當(dāng)self釋放時(shí)驼修,weakSelf已經(jīng)等于nil殿遂。
擴(kuò)展:NSTimer注意避免循環(huán)引用的地方,需要找個(gè)合適的時(shí)機(jī)和地方來 invalidate timer
在引用計(jì)數(shù)的環(huán)境里面,默認(rèn)情況下當(dāng)你在block里面引用一個(gè)Objective-C對(duì)象的時(shí)候乙各,該對(duì)象會(huì)被retain墨礁。當(dāng)你簡單的引用了一個(gè)對(duì)象的實(shí)例變量時(shí),它同樣被retain耳峦。但是被__block存儲(chǔ)類型修飾符標(biāo)記的對(duì)象變量不會(huì)被retain
注意:在垃圾回收機(jī)制里面恩静,如果你同時(shí)使用__weak和__block來標(biāo)識(shí)一個(gè)變量,那么該block將不會(huì)保證它是一直是有效的。 如果你在實(shí)現(xiàn)方法的時(shí)候使用了block,對(duì)象的內(nèi)存管理規(guī)則更微妙:也是(__weak與__block區(qū)別:)
1驶乾、如果你通過引用來訪問一個(gè)實(shí)例變量邑飒,self會(huì)被retain。
2级乐、如果你通過值來訪問一個(gè)實(shí)例變量疙咸,那么變量會(huì)被retain