第2章 Blocks
? ? 2.1 什么事Blocks:是C語言的擴充功能揪漩。帶有自動變量(局部變量)的匿名函數(shù)狞尔。
? ? ? ?C語言中函數(shù)可能使用的變量:
????????????自動變量(局部變量)
????????????函數(shù)的參數(shù)
????????????靜態(tài)變量(靜態(tài)局部變量)
????????????靜態(tài)全局變量
????????????全局變量??? ?
? ? ? ?后三個在函數(shù)多次調用之間能夠傳遞值?? ?
?? ?? ? 在計算機科學中修己,此概念也稱為閉包(Closure)父阻、lambda計算浓冒。
?? ?? ? C + Blocks ? ? ? ? ? Block
?? ?? ? Smalltalk?? ??? ?? ? ? Block
?? ?? ? Ruby?? ??? ??? ??? ?? ? Block
?? ?? ? Python?? ??? ??? ??? ??Lambda
?? ?? ? C++??? ??? ??? ??? ??? ??Lambda
?? ?? ? JS?? ??? ??? ??? ??? ??? ? Anonymous function
? ? 2.2 Blocks 模式
?? ?? ? 2.2.1 語法:1笔刹、沒有函數(shù)名 2、帶有^
?? ??? ?? ? ^void ( int event ) {
?? ??? ??? ??? ?? ? printf();
? ? ? ? ? ?}
?? ??? ?? ? ^ 返回值類型 參數(shù)列表 表達式 :無返回值溪窒,返回值類型省略坤塞。無參數(shù)時,參數(shù)列表省略澈蚌。
?? ?? ? 2.2.2 Block 類型變量
?? ??? ?? ? C語言中 int (*funcptr)(int) = &func; 函數(shù)func的地址就賦值給函數(shù)指針類型變量funcptr中了
?? ??? ?? ? Block既指源代碼中的Block語法摹芙,也指有Block語法生成的值。
?? ??? ?? ? 聲明Block類型的變量 ?int (^blk)(int); ?與一般的C語言變量完全相同宛瞄。
?? ??? ?? ? typedef int(^blk_t)(int) 聲明blk_t類型的變量浮禾。
?? ??? ?? ? Block類型變量指針,即Block的指針類型變量
?? ??? ?? ? blk_t blk = ^(int count){return count + 1; };
?? ??? ?? ? blk_t *blkptr = &blk;
?? ??? ?? ? (*blkptr)(10);
?? ?? ? 2.2.3 截獲自動變量值 ?Block使用的是它之前聲明的自動變量份汗。
?? ?? ? 使用附有__block 說明符的自動變量可在Block中賦值盈电,該變量稱為__block變量
?? ?? ? 截獲的自動變量可以被使用陕壹,但不可給截獲的自動變量賦值绸硕。若想賦值使用__block修飾
? ? 2.3 Blocks 的實現(xiàn)
?? ?? ? 帶有自動變量值的匿名函數(shù)友绝。實際上是作為極普通的C語言源代碼來處理的沧卢。
?? ?? ? 所謂Block就是Objective-C對象
?? ?? ? 所謂“截獲自動變量”意味著在執(zhí)行Block語法時铸鹰,Block語法表達式所使用的自動變量值被保存到Block的結構體實例中具温。
?? ?? ? 不能改寫被截獲的自動變量的值岭佳。
?? ?? ? 在Block中保存值:
????????????????靜態(tài)變量怪瓶、靜態(tài)全局變量均践、全局變量
????????????????使用__block說明符(修飾的自動變量生成結構體實例晤锹,有一個__forwarding結構體指針指向自身)
? ? ? a. ?NSConcreteStackBlock Block對象設置在棧上 ?copy ?從棧復制到堆
?? ??? ??? ?? ? 設置在棧上的Block,其所屬的變量作用域結束,該Block被廢棄彤委。__block變量也一樣鞭铆。
? ? ? ?b. NSConcreteGlobalBlock Block對象設置在程序的數(shù)據(jù)區(qū)域(.data區(qū))上? ? 什么也不做
?? ??? ??? ?? ? 使用全局變量的地方不能使用自動變量,所以不存在自動變量截獲焦影。
?? ??? ??? ?? ? Block結構體實例的內容不依賴于執(zhí)行時的狀態(tài)车遂,所以整個程序只需一個實例
?? ??? ??? ?? ? 只要Block不截獲自動變量,就可以將Block用結構體實例設置在程序的數(shù)據(jù)區(qū)域
? ? ? ?c. NSConcreteMallocBlock Block對象設置在內存塊(即堆)上? ? 引用計數(shù)增加
?? ??? ??? ?? ? __block變量會跟隨Block從棧復制到堆時一起被賦值斯辰,此時Block持有__block變量舶担。
?? ??? ??? ?? ? 別的Block從棧復制到堆時,被復制的Block持有的__block變量彬呻,并增加__block變量的引用計數(shù)
?? ??? ??? ?? ? 堆上的Block被廢棄衣陶,它所使用的__block也被釋放柄瑰。(沒有持有者被廢棄)
?? ??? ??? ??? ?__block復制到堆之后,棧上的__block變量的__forwarding結構體指針指向復制到堆上的__block變量用結構體的指針
?? ?? ? 將BLock作為函數(shù)返回值返回時剪况,編譯器會自動生成復制到堆上的代碼
?? ?? ? 不需要手動復制:
?? ??? ?? ? Cocoa框架下的方法且方法名中含有usingBlock
?? ??? ?? ? GCD的API
?? ?? ? 截獲對象:
?? ?? ? _Block_object_assgin()相當于retain實例方法教沾,將對象賦值在對象類型的結構體成員變量中 ? ? 棧上的Block復制到堆時
?? ??? ?_Block_object_dispose()相當于release實例方法,釋放賦值在對象類型的結構體成員變量中的對象?? ?? ?堆上的Block被廢棄時
?? ?? ? 什么時候棧上的Block會復制到堆上译断?
????????????調用Block的copy實例方法
? ? ? ? ? ? ?Block作為函數(shù)的返回值返回
????????????將Block賦值給附有__strong修飾符id類型的類或Block類型成員變量時
????????????方法名中含有usingBlock的Cocoa框架方法或GCD的API(Grand Central Dispatch)
?? ?? ? Block循環(huán)引用:
?? ??? ?? ? 對象持有Block授翻,Block持有對象self?? ?? ? 使用weak修飾符,避免造成循環(huán)引用
?? ??? ?? ? A->B->A? ? 也可以使用__block變量來避免循環(huán)引用(必須執(zhí)行Block)
?? ??? ?? ? A->B->C->A
?? ?? ? ARC無效時孙咪,一般需要手動將Block從棧復制到堆堪唐。用copy來復制,用release來釋放翎蹈。retain來持有淮菠。
? ? ? ? 此時用__Block說明符來避免Block中的循環(huán)引用
PS:加深記憶