首先,對於沒有引用外部變數的block,無論在arc還是非arc下,型別都是__nsglobalblock__,這種型別的block可以理解成一種全域性的block,不需要考慮作用域問題。同時,對他進行copy或者retain操作也是無效的,比如這樣乙個返回block的函式:
typedef在非arc下執行如下**:int(^myblock)();
myblock
func()
;}
//輸出:非arc
myblock
block =
func
();nslog
(@"%d"
, block());
nslog
(@"%@"
, [block
class
]);myblock
block2 = [block
copy
];//copy
操作對__nsglobalblock__
型別無效
nslog
(@"%d"
, block == block2);
123可以看到,copy後的block和原來是同乙個物件的。__nsglobalblock__
1
而對於引用了外部變數的block,如果沒有對他進行copy,他的作用域只會在宣告他的函式棧內(型別是__nsstackblock__),如果想在非arc下直接返回此類block,xcode會提示編譯錯誤的,如下圖:
(xcode提示returning block that lives on the local stack)
而在arc環境下,上述**會編譯通過,因為arc會自動加入copy操作。
比如可以在arc下執行如下**:
//arc輸出:myblock
block =
func
();nslog
(@"%d"
, block());
nslog
(@"%@"
, [block
class
]);
123型別是__nsmallocblock__,說明block已經被copy到了堆中了。__nsmallocblock__
當然其實在非arc下,也可以使上面有錯誤的函式編譯通過。如下**:
typedef我們把原來的返回值賦給乙個變數,然後再返回這個變數,就可以編譯通過了。不過雖然編譯通過了,這個返回的block作用域仍是在函式棧中的,因此一旦函式執行完畢後再使用這個block很可能會引發bad_access錯誤。int(^myblock)();
myblock
func()
;return
ret;
}
所以在非arc下,必須把block複製到堆中才可以在函式外使用block,如下正確的**:
typedef我們可以直接通過輸出變數的指標,就可以驗證block被copy後,他所引用的變數被複製到了堆中的情況,如下**(非arc下):int(^myblock)();
myblock
func()
copy
];}
//輸出:非arc
void
func()
;block = [block
copy
];block();
nslog
(@"%@"
, @"=== block copy後"
);nslog
(@"&a = %p, &b = %p"
, &a, &b);
nslog
(@"a = %d, b = %d"
, a, b);
[block
release
];}
=== block copy前可以看到,在block執行中,他所引用的變數a和b都被複製到了堆上。而被標記__block的變數事實上應該說是被移動到了堆上,因此,當block執行後,函式棧內訪問b的位址會變成堆中的位址。而變數a,仍會指向函式棧內原有的變數a的空間。&a = 0x7fff5fbff8bc, &b = 0x7fff5fbff8b0
=== block
&a = 0x100201048, &b = 0x100201068
a = 123, b = 456
=== block copy後
&a = 0x7fff5fbff8bc, &b = 0x100201068
a = 123, b = 456
非ARC下返回Block
首先,對於沒有引用外部變數的block,無論在arc還是非arc下,型別都是nsglobalblock,這種型別的block可以理解成一種全域性的block,不需要考慮作用域問題。同時,對他進行copy或者retain操作也是無效的,比如這樣乙個返回block的函式 typedef int mybl...
ARC和非ARC下使用Block屬性的問題
block屬性的宣告,首先需要用copy修飾符,因為只有copy後的block才會在堆中,棧中的block的生命週期是和棧繫結的。另乙個需要注意的問題是關於執行緒安全,在宣告block屬性時需要確認 在呼叫block時另乙個執行緒有沒有可能去修改block?這個問題,如果確定不會有這種情況發生的話,...
Block在ARC和非ARC中的使用
1 block是事先封裝好的一段 快,在需要的時候呼叫block執行 block底層是指向結構體的指標,編譯器會將block的內部 生成c語言對應的函式 2 block預設是存放在棧中的 開發人員不需要管理記憶體 儲存在棧中的block不會對引用的物件進行retain 3 非arc 對block進行...