block屬性的宣告,首先需要用copy
修飾符,因為只有copy
後的block才會在堆中,棧中的block的生命週期是和棧繫結的
《棧 :由系統維護的區域性變數 是存在棧上的,其生命週期隨函式的生命週期》
《堆 :由程式設計師申請空間位址,由程式設計師手動釋放,生命週期受到程式設計師控制》
使用retain也可以,因為block的retain行為預設是用copy的行為實現的,block變數預設是宣告為棧變數的,為了能夠在block的宣告域外使用,所以要把block拷貝(copy)到堆,所以說為了block屬性宣告和實際的操作一致,最好宣告為copy。
另乙個需要注意的問題是關於執行緒安全,在宣告block屬性時需要確認「在呼叫block時另乙個執行緒有沒有可能去修改block?」這個問題,如果確定不會有這種情況發生的話,那麼block屬性宣告可以用nonatomic
。如果不肯定的話(通常情況是這樣的),那麼你首先需要宣告block屬性為atomic
,也就是先保證變數的原子性(objective-c並沒有強制規定指標讀寫的原子性)。
但是,有了atomic
來保證基本的原子性還是沒有達到執行緒安全的,接著在呼叫時需要把block先賦值給本地變數,以防止block突然改變。因為如果不這樣的話,即便是先判斷了block屬性不為空,在呼叫之前,一旦另乙個執行緒把block屬性設空了,程式就會crash,如下**:
if (self.myblock)
所以正確的**是(arc):
myblocktype block = self.myblock;//block現在是本地不可變的
if (block)
在非arc下則需要手動retain
一下,否則如果屬性被置空,本地變數就成了野指標了,如下**:
//非arcmyblocktype block = [self.myblock retain];
if (block)
[block release];
迴圈引用是另乙個使用block時常見的問題。
在arc下,由於__block
抓取的變數一樣會被blockretain
,所以必須用弱引用才可以解決迴圈引用問題,ios 5之後可以直接使用__weak
,之前則只能使用__unsafe_unretained
了,__unsafe_unretained
缺點是指標釋放後自己不會置空。示例**:
//ios 5之前可以用__unsafe_unretained//__unsafe_unretained typeof(self) weakself = self;
__weak typeof(self) weakself = self;
self.myblock = ^(int paramint)
;
//非arc__block typeof(self) weakself = self;
self.myblock = ^(int paramint)
;
建議132 考慮用類名作為屬性名
建議132 考慮用類名作為屬性名 一般來說,若果屬性對應乙個型別,應該直接用型別名命名屬性名。如下 class person class company 沒有必要為屬性名指定另外的名字,如 public company thecompany當然,除非我們的型別當中有多個company型別的屬性,這樣...
類A的物件作為類B的成員時,類A的建構函式如何呼叫
class a class b int main int argc,const char ar 執行結果 可以看出類a先於類b構造,這是符合構造類物件時的執行順序的。由於類a和類 都是空類,雖然類 包含了類 的物件,然而他們所占用的記憶體大小依舊都是 class a class b int main...
用BeanUtils框架操作類的屬性
首先匯入 commons logging.jar commons beanutils 1.8.0.jar 這兩個架包用beanutils框架操作類的屬性 test public void test1 throws exception,invocationtargetexception test pu...