本文主要介紹 Block 的三種類型。
一、Block 是什么?
在 OC 文檔的 Working with Blocks 中:
Blocks are Objective-C objects, which means they can be added to collections like NSArray
or NSDictionary
.
Block 官方文檔: Block Programming Topics 中:
As an optimization, block storage starts out on the stack—just like blocks themselves do.
block 是一個 OC 對象,但是它和普通的O從對象又不一樣。
block 默認在 棧上分內存,而我們一般的對象是在堆上。
二、block 有三種類型: 全局 / 棧 / 堆 block
1、全局block - __NSGlobalBlock__
- (void)block3 { // 聲明: typedef NSString *(^MyBlock)(NSString *str); MyBlock block = ^(NSString *str){ NSLog(@"處理一些無關於外部屬性的事務"); return str; }; block(@""); NSLog(@"block類型%@",block); }
2、棧block - __NSStackBlock__
- (void)block2 { int a = 1; NSLog(@"block類型%@",^{ NSLog(@"block 0:%i", a); }); }
3、堆block - __NSMallocBlock__
- (void)block1 { void (^blockObject)(void); blockObject = ^{ NSLog(@"block 0:%i", a); }; blockObject(); NSLog(@"block類型%@",blockObject); }
從上面3部分代碼中,我們可看出三者區別:
全局block:block 沒有訪問任何外部變量的;
棧block: block 訪問了外部對象,但沒有copy操作;
堆block:相對於棧block來說:我們聲明定義了一個block同時訪問了外部變量則(不訪問就是全局)(不聲明定義就是棧),此過程本質就是棧-變->堆的過程,系統幫我們做了copy,棧的block遷移到了堆里。
4、關於堆block 詳解
代碼示例:
- (void)block1 { /* __block 允許block內部使用, */ __block NSString *blockStr = @"局部str"; MyBlock block = ^(NSString *str){ /* block 內部操作:將對象 copy 了一個新的到堆上,指針不變,但指針指向新的對象 */ self->globalStr = @"block內修改全局"; blockStr = str; NSLog(@"內globalStr== %@ %p %p",self->globalStr,self->globalStr,&self->globalStr); [self logstr:blockStr]; return str; }; NSLog(@"block類型%@",block); NSLog(@"外globalStr== %@ %p %p",globalStr,globalStr,&globalStr); NSLog(@"外blockStr== %@ %p %p",blockStr,blockStr,&blockStr); block(@"執行block,改局部str"); } - (void)logstr:(NSString *)blockStr { NSLog(@"globalStr2== %@ %p %p",globalStr,globalStr,&globalStr); /* 局部str,拿到外部,創建了一個新的指向它的指針 */ NSLog(@"blockStr2== %@ %p %p",blockStr,blockStr,&blockStr); }
運行結果如圖:
我們可以看到,不論是函數中的局部變量 還是當前文件范圍的局部變量(注意:代碼里的‘全局’並非是真正的全局,只是為了用來區分函數內部變量), 在 block 內部進行使用,對象都不是外部的那個對象了,但是指向對象的指針不變 --> 即:指針指向的對象是一個copy出來的新的。如下圖:
從而,也可知,block內部會對我們的對象進行copy,但是指向對象的指針不變,指針指向對象會變成新的。
而函數內部的局部變量被拿出去函數外部使用時,相當於 創建了一個新 的指向這個改變后對象的 指針。
待續... ...
以上。