国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS開發筆記之五十八——ARC下的block類型分析

2019-11-09 18:12:02
字體:
來源:轉載
供稿:網友

這里有篇唐巧的博客:http://blog.devtang.com/2013/07/28/a-look-inside-blocks/,根據文中介紹,block一共存在以下三種類型:

1、_NSConcreteGlobalBlock全局的靜態 block,不會訪問任何外部變量;

2、_NSConcreteStackBlock保存在棧中的 block,當函數返回時會被銷毀;

3、_NSConcreteMallocBlock保存在堆中的 block,當引用計數為0時會被銷毀;

文中還指出,ARC下只存在NSConcreteGlobalBlock 和 NSConcreteMallocBlock類型的block;下面我就通過一個例子來一探討究竟。

定義了MyTestBlock類,如下:

#import <Foundation/Foundation.h>@interface MyTestBlock : NSObject@PRoperty (nonatomic, copy) void(^block)();@end
#import "MyTestBlock.h"@implementation MyTestBlock- (void)dealloc{    NSLog(@"------>dealloc");}- (instancetype)init{    self = [super init];    if (self)    {        self.block = ^{            NSLog(@"my test block run...");        };         NSLog(@"the kind of self.block:%@...",self.block);    }    return self;}@end

另外,本工程是在ARC下執行的。

1、NSGlobalBlock類型的block:

此時my.block的屬性修飾是copy,如下:

@property (nonatomic, copy) void(^block)();

main函數中調用如下:
#import <Foundation/Foundation.h>#import <objc/runtime.h>#import "MyTestBlock.h"int main(int argc, const char * argv[]){    @autoreleasepool    {        MyTestBlock *testBlock = [[MyTestBlock alloc] init];        testBlock.block();    }    while (1) {;}    return 0;}打印結果如下:

2017-02-07 11:09:03.398 myBlock[27892:414636] the kind of self.block:<__NSGlobalBlock__: 0x100001090>...這是一個Global類型的block,此時的block內部沒有訪問它之外的變量,修飾詞不管是copy還是strong或者其他,都不會改變。

2、NSMallocBlock類型的block:

__weak typeof(self) weakSelf = self;self.block = ^{    __strong typeof(weakSelf) strongSelf = weakSelf;    NSLog(@"%@",strongSelf);    NSLog(@"my test block run...");    };NSLog(@"****************>:%@",self.block);打印結果如下:

2017-02-07 11:19:53.093 myBlock[27986:420865] ****************>:<__NSMallocBlock__: 0x100200360>

此時self.block的修飾詞是copy或者strong。

3、NSStackBlock類型的block:此時修改property屬性為assign,如下:

@property (nonatomic, assign) void(^block)();打印結果如下:

打印結果如下:2017-02-07 11:26:46.697 myBlock[28143:428428] ****************>:<__NSStackBlock__: 0x7fff5fbff720>(lldb) 不過此時會報出BAD_access錯誤:

棧block在init執行完時,空間就已經釋放,此時的訪問等同于訪問一個野指針。有人可能會想,如果我們把assgin改為weak,ARC對于釋放的對象會自動置為nil,這樣不就不會crash了嗎?我們來試一試,如下:

@property (nonatomic, weak) void(^block)();

打印結果如下:

2017-02-07 11:33:31.330 myBlock[28240:434797] ****************>:<__NSStackBlock__: 0x7fff5fbff720>但是仍會BAD_ACCESS。此時,ARC對于指向存儲在棧中的對象,并沒有自動置為nil。可以看出ARC下其實是存在NSStackBlock類型的block的,只不過對于ARC的weak操作,它是無效的;

針對以上,我來分析下以下幾個問題:

1、為什么沒有捕獲變量的block會是Global的?Global意味著一般有以下幾個特點,只讀、運行前大小確定,一般存儲在程序的代碼段Code Segment,這里一般存放字符串常量等;為什么OC的編譯器會把這種block當作常量一樣存放在內存的代碼段區呢?其實這也很好理解,我們都知道block clang后代碼其實就是C的struct結構,它的大小是編譯階段就可以明確的了,內部的執行也類似于普通的函數調用一樣,不需要內存管理,所以被存儲在代碼段也就理所當然了。

2、NSStackBlock類型的Block是否支持ARC的其他操作呢?

這個問題比較復雜,構造一個非類屬性的block,先看下代碼示例:

__weak typeof(self) weakSelf = self;NSLog(@"%@",  ^{    __strong typeof(weakSelf) strongSelf = weakSelf;    NSLog(@"%@",strongSelf);    NSLog(@"my test block run..."); });打印結果如下:
<__NSStackBlock__: 0x7fff5fbff720>說明self.block=^{};等號右邊的block本身是個棧block,經過OC的賦值(OC的賦值默認是strong)操作以后,使self.block指向了堆block。這個中間OC編譯器將棧block進行了一次拷貝到堆區,便于ARC管理。

3、堆上的block再進行copy操作后?

我們再對堆上的block進一步進行copy,如下:

NSLog(@"****************>:%@",self.block);void (^myBlock)() = [self.block copy];NSLog(@"****************>:%@",myBlock);打印的如下:

****************>:<__NSMallocBlock__: 0x100106d40>****************>:<__NSMallocBlock__: 0x100106d40>這兩個block指向了同一個block,說明堆block的copy操作只是copy了一個引用。

巧哥文中說的ARC下只有堆和global類型的block,是以block最終的存在形式,并沒有考慮到一些“中間態”的block。

4、參考資料:

http://www.jianshu.com/p/61ff80d310f4

http://blog.devtang.com/2013/07/28/a-look-inside-blocks/


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 西峡县| 武山县| 科技| 铜陵市| 西青区| 平湖市| 昌都县| 鄂尔多斯市| 民丰县| 壶关县| 安吉县| 阳原县| 溧水县| 汶川县| 凤庆县| 嘉鱼县| 池州市| 高雄市| 永靖县| 友谊县| 红桥区| 山东省| 莱阳市| 个旧市| 峨山| 曲靖市| 西和县| 桦甸市| 浦北县| 河间市| 城固县| 庆城县| 理塘县| 南昌市| 牙克石市| 金山区| 碌曲县| 碌曲县| 时尚| 明光市| 九寨沟县|