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

首頁 > 學院 > 開發設計 > 正文

Objective-C中Blocks塊的介紹

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

*注:解釋內容主要參考《Objective-C 高級編程》

1.介紹:

  Blocks是C語言的擴充功能:帶有自動變量(局部變量)的匿名函數。

  Blocks的語法:^  返回值類型  參數列表  表達式

  例如:

^int (int c){return c+1;}其中,返回值類型 是可以省略的,會按return類型返回,如果不需要參數,那么參數列表 也可以省略,如:

^{PRintf("hello");}

2.Block類型變量

    int (^blk)(int) = ^(int c){return c+1;};        int x = blk(5);        NSLog(@"x = %d",x);Block值^(int c){return c+1;} 被賦值給了變量blk中,blk即為Block變量。

利用typedef定義Block別名:

    typedef int (^blk_1)(int);        blk_1 blkk = ^(int x){return x+3;};        NSLog(@"x = %d",blkk(3));意指用blk_1來代替int ^(int);這種塊,之后調用賦值什么的會更舒服。

3.截獲自動變量值

    int x = 1;    void (^blk)(void) = ^{        NSLog(@"zhi = %d",x);    };        x = 6;        blk();以上代碼輸出結果 zhi = 1;可見在Block截獲的是自動變量x的值,之后改變x,并不會對塊的執行結果有影響。并且我們如果想在塊中改變x的值是無法通過編譯的。如果我們想在塊中改變x的值,需要用__block說明符

4.__block說明符

    __block int x = 1;        void (^blk)(void) = ^{        x = 6;    };    blk();        NSLog(@"x = %d",x);

輸出結果為 x = 6

用__block修飾x后,便可以在塊中改變截取的自動變量x,那么:

    __block int x = 1;        void (^blk)(void) = ^{        NSLog(@"x = %d",x);    };    x = 7;        blk();輸出結果為 x = 7

這里思考,如果我們不用__block,截取OC對象,會怎么樣:

    NSString *age = @"26";    NSMutableDictionary *dic =[[NSMutableDictionary alloc]init];    [dic setObject:age forKey:@"age"];        void (^blk)(void) = ^{        NSString *a = [dic objectForKey:@"age"];        NSLog(@"age = %@",a);    };        NSString *age2 = [dic objectForKey:@"age"];    age2 = @"18";    [dic removeObjectForKey:@"age"];    [dic setObject:age2 forKey:@"age"];        blk();

輸出結果為 age = 18

這里我們初始化了一個dic,里面有一個key為@"age"的NSString,初始值為26,在塊中輸出字典中字符串的值,然后在塊執行前,改變dic中字符串。

由此我們聯想:

    NSString *age = @"26";    NSMutableDictionary *dic =[[NSMutableDictionary alloc]init];    [dic setObject:age forKey:@"age"];        void (^blk)(void) = ^{        NSString *age2 = [dic objectForKey:@"age"];        age2 = @"18";        [dic removeObjectForKey:@"age"];        [dic setObject:age2 forKey:@"age"];    };      blk();    NSString *a = [dic objectForKey:@"age"];    NSLog(@"age = %@",a);

輸出 age = 18

所以在塊中也能改變dic的值。

這里我們分析,我們用塊截取的是NSMutableDIcitionary的實例指針,不能對其賦值,但是可以使用它,即可以向其中添加改變對象。

*這里我們要注意:

   const char text[] = "HelloWorld";   const char *text1 = "HelloWorld";        void (^blk)(void) = ^{        printf("%c",text1[1]);    };        blk();我們可以使用截取*text1,但是text[]不可以,因為截取自動變量的方法并沒有實現對C語言數組的接獲,應該用指針方法解決。4.Blocks的實現

那么這種截取自動變量以及__block修飾變量,背后是怎樣實現的呢,本文簡單介紹一下有關截取變量這里,至于Blocks實現的詳細解析放在后續文章中。

我們利用clang的指令轉變一下我們的文件,打開終端,利用 clang -rewrite-objc ‘文件名’ 對我們的文件進行操作,我們的文件內容如下:

int main(){        int i = 10;        int (^blk)(void) = ^{        int x = i+1;        return x;    };        int jieguo = blk();        return 0;}聲明一個簡單的塊,截獲了自動變量 int i,我們用clang指令操作它得到.cpp文件:

struct __main_block_impl_0 {  struct __block_impl impl;  struct __main_block_desc_0* Desc;  int i;  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _i, int flags=0) : i(_i) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};//塊中函數static int __main_block_func_0(struct __main_block_impl_0 *__cself) {  int i = __cself->i; // bound by copy        int x = i+1;        return x;}由于轉化后代碼太多,就只截取了一部分。可以看到結構體構造函數初始化 i(_i) , 讓i = _i,這是一個copy的過程,所以外部改變自動變量的值,不會影響到塊中的值。

如果使用__block修飾的話:

struct __Block_byref_i_0 {  void *__isa;__Block_byref_i_0 *__forwarding; int __flags; int __size; int i;};struct __main_block_impl_0 {  struct __block_impl impl;  struct __main_block_desc_0* Desc;  __Block_byref_i_0 *i; // by ref  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};static int __main_block_func_0(struct __main_block_impl_0 *__cself, int x) {  __Block_byref_i_0 *i = __cself->i; // bound by ref        int y = x + (i->__forwarding->i);        return y;}可以看到,在構造函數中,i(_i->__forwarding) , 這里用一個結構體__Block_byref_i_0,以指針的方式去保存自動變量,保存了變量的地址,那么后續改變自動變量,塊中的值也會相應改變。有關塊循環引用的問題,及各種使用會在后面文章中介紹。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 乐业县| 白沙| 大连市| 石棉县| 开远市| 通海县| 白城市| 长武县| 龙海市| 兰溪市| 砀山县| 富顺县| 奉新县| 新田县| 新宁县| 聂拉木县| 台中市| 新绛县| 奇台县| 志丹县| 仙游县| 库尔勒市| 贵定县| 东辽县| 通化市| 林口县| 苗栗县| 吴江市| 化州市| 余姚市| 高唐县| 长顺县| 洛扎县| 抚宁县| 武邑县| 安化县| 麟游县| 景泰县| 信丰县| 辛集市| 章丘市|