轉(zhuǎn):
簡單來說懦趋,block就像一個函數(shù)指針击你,指向我們要使用的函數(shù)偏形。
就和函數(shù)調(diào)用一樣的,不管你在哪里寫了這個block寡痰,只要你把它放在了內(nèi)存中(通過調(diào)用存在這個block的方法或者是函數(shù))抗楔,不管放在棧中還是在堆中,還是在靜態(tài)區(qū)拦坠。只要他沒有被銷毀连躏,你都可以通過你聲明的block調(diào)用他。
說到在類中聲明一個block為什么要用copy修飾的話贞滨,那就要先說block的三種類型入热。
1._NSConcreteGlobalBlock
全局的靜態(tài)block拍棕,不會訪問外部的變量。就是說如果你的block沒有調(diào)用其他
的外部變量勺良,那你的block類型就是這種绰播。例如:你僅僅在你的block里面寫一個NSLog("hello world");
2._NSConcreteStackBlock
保存在棧中的 block,當函數(shù)返回時會被銷毀尚困。這個block就是你聲明的時候不用copy修飾蠢箩,并且你的block訪問了外部變量。
3._NSConcreteMallocBlock
保存在堆中的 block事甜,當引用計數(shù)為 0 時會被銷毀谬泌。好了,這個就是今天的主角 逻谦,用copy修飾的block掌实。
我們知道,函數(shù)的聲明周期是隨著函數(shù)調(diào)用的結(jié)束就終止了跨跨。我們的block是寫在函數(shù)中的潮峦。
如果是全局靜態(tài)block的話,他直到程序結(jié)束的時候勇婴,才會被被釋放。但是我們實際操作中基本上不會使用到不訪問外部變量的block嘱腥「剩【但是在測試三種區(qū)別的時候,因為沒有很好的理解這種block齿兔,(用沒有copy修飾和沒有訪問外部變量的block)試了好多次橱脸,以為是放在靜態(tài)區(qū)里面的block沒有隨函數(shù)結(jié)束被釋放。這是個小坑】
如果是保存在棧中的block分苇,他會隨著函數(shù)調(diào)用結(jié)束被銷毀添诉。從而導致我們在執(zhí)行一個包含block的函數(shù)之后,就無法再訪問這個block医寿。因為(函數(shù)結(jié)束栏赴,函數(shù)棧就銷毀了,存在函數(shù)里面的block也就沒有了)靖秩,我們再使用block時须眷,就會產(chǎn)生空指針異常。
如果是堆中的block沟突,也就是copy修飾的block花颗。他的生命
周期就是隨著對象的銷毀而結(jié)束的。只要對象不銷毀惠拭,我們就可以調(diào)用的到在堆中的block扩劝。
這就是為什么我們要用copy來修飾block。因為不用copy修飾的訪問外部變量的block,只在他所在的函數(shù)被調(diào)用的那一瞬間可以使用棒呛。之后就消失了聂示。