標籤:另一個 複製 執行 ios release 變數 argv 對象 jad
//最近總是犯迷糊,關於block對外部變數的引用,今天有時間就寫了一下,加深自己的理解,鞏固基礎知識
1 #import <Foundation/Foundation.h> 2 int gNum = 100; 3 int main(int argc, const char * argv[]) { 4 @autoreleasepool { 5 static int sNum = 100; 6 __block int bNum = 100; 7 int lNum = 100; 8 int (^sum)(int, int) = ^(int a, int b) { 9 NSLog(@"%d %d %d %d",sNum,gNum,lNum,bNum);10 sNum++;11 bNum++;12 gNum++;13 return a + b + lNum + gNum + sNum + bNum ; 14 };15 sNum = 1;16 bNum = 1;17 gNum = 1;18 lNum = 1;19 20 NSLog(@"%d",sum(1,2));21 NSLog(@"%d",sNum);22 NSLog(@"%d",bNum);23 NSLog(@"%d",gNum);24 NSLog(@"%d",lNum);25 26 }27 return 0;28 }
列印結果
1 12:57:09.984 xxx[10180:2208151] 1092 12:57:09.984 xxx[10180:2208151] 23 12:57:09.984 xxx[10180:2208151] 24 12:57:09.984 xxx[10180:2208151] 25 12:57:09.984 xxx[10180:2208151] 1
Block其實包含兩個部分內容
1.Block執行的代碼,這是在編譯的時候已經產生好的;
2.一個包含Block執行時需要的所有變數值的資料結構。Block將使用到的,範圍附近的變數的值建立一份快照拷貝到棧上。
Block與函數另一個不同是,Block類似Objc的對象,可以使用自動釋放池管理記憶體
3 Block對外部變數的存取管理
基礎資料型別 (Elementary Data Type)
1,局部變數
局部自動變數,在Block中唯讀。Block定義時copy變數的值,在Block中作為常量使用,所以即使變數的值在Block外改變,也不影響他在Block中的值。
2, static修飾符的靜態變數或全域變數
因為全域變數貨靜態變數在記憶體中的地址是固定的,Block在讀取改變數值的時候是直接從其所在的記憶體讀出的,擷取daode 是最新值,而不是在定義時copy的常量。
3,__block修飾的變數
block變數,在被__block修飾的變數稱作Block變數。基本類型的Block變數等小雨全域變數或靜態變數。Block的使用很像函數指標,不過與函數最大的不同是:Block可以訪問函數以外,詞法範圍以內的外部變數的值。
二、物件類型
//本機物件
- (void)localObjTest { UILabel *localObj = [[UILabel alloc]init]; NSLog(@"localObj adress --%p", & localObj); void (^test)() = ^{ NSLog(@"localObj adress --%p", & localObj); NSLog(@"localObj --%@",localObj); }; localObj = nil; test(); }
列印結果:
2018-03-17 13:44:25.848 test1[1332:79267] localObj adress-- 0xbff7ced42018-03-17 13:44:25.848 test1[1332:79267] localObj adress-- 0x7b63f8b42018-03-17 13:44:25.848 test1[1332:79267] localObj --<UILabel: 0x7c8337a0; frame = (0 0; 0 0);
//靜態對象 - (void)staticObjTest { static UILabel *staticObj ; staticObj = [[UILabel alloc]init]; NSLog(@"staticObj adress --%p", & staticObj); void (^test)() = ^{ NSLog(@"staticObj adress --%p", & staticObj); NSLog(@"staticObj --%@",staticObj); }; staticObj = nil; test(); }
列印結果:
2018-03-17 13:44:25.917 test1[1332:79267] staticObjadress -- 0x85a482018-03-17 13:44:25.917 test1[1332:79267] staticObjadress -- 0x85a482018-03-17 13:44:25.917 test1[1332:79267] staticObj --(null)
//全域對象 - (void)globalObjTest { globalObj = [[UILabel alloc]init]; NSLog(@"staticObj adress --%p", & globalObj); void (^test)() = ^{ NSLog(@"globalObj adress --%p", & globalObj); NSLog(@"globalObj --%@",globalObj); }; globalObj = nil; test(); }
列印結果:
2018-03-17 13:44:25.917 test1[1332:79267] staticObjadress -- 0x85a4c2018-03-17 13:44:25.917 test1[1332:79267] globalObjadress -- 0x85a4c2018-03-17 13:44:25.917 test1[1332:79267] globalObj --(null)
//block對象 - (void)blockObjTest { __block UILabel *blockObj = [[UILabel alloc]init]; NSLog(@"blockObj adress --%p", & blockObj); void (^test)() = ^{ NSLog(@"blockObj adress --%p", & blockObj); NSLog(@"blockObj --%@",blockObj); }; blockObj = nil; test(); }
列印結果:
2018-03-17 13:44:25.917 test1[1332:79267] blockObj adress-- 0xbff7ced02018-03-17 13:44:25.918 test1[1332:79267] blockObj adress-- 0x7c8355982018-03-17 13:44:25.918 test1[1332:79267] blockObj --(null)
總結:從測試結果可以看到
*對於靜態物件變數和全域物件變數,其地址同樣不是固定的。
*對於局部(本地)物件變數,定義block的時候同樣複製了(指標)變數,其在block中是作為(指標)常量使用的,不會受外界影響。
*對於block物件變數,定義block的時候同樣將變數從棧轉移到了堆上,這一點用剛才的方法同樣可以驗證。因此block變數是受外界影響的,導致輸出結果為空白。
iOS中block 靜態全域局部變數block變數,以及對象,詳解!