zl程序教程

您现在的位置是:首页 >  后端

当前栏目

obj-c编程09:块的语法

编程 语法 09 OBJ
2023-09-14 08:56:51 时间

    在obj-c中,有一种和C截然不同的东西——块。块可以在外边定义,也可以在函数或方法内部定义,可以被赋值给一个变量,然后用该变量调用。默认情况下块对外部变量的访问只能读不能写,除非用__block显示声明可写。对于块这么个东东,让我想到了ruby中的block,不过ruby中block是闭包,而且外部变量变化会影响block的值,但obj-c的块不会,即obj-c块的外部变量是编译时求值而不是运行时求值哦:

#import Foundation/Foundation.h 

int main(int argc,char *argv[])

 @autoreleasepool{

 int i = 10;

 //foo是一个块变量被赋值为一个块。

 int (^foo)(int) = ^(int x) {

 int ret = x * i;

 //i = 100; 编译错误,不能改写外部变量的值

 NSLog(@"%d * i(%d) = %d",x,i,ret);

 return ret;

 i = 1000;

 foo(11); //i此时为10而不是1000哦。

 return 0;


可以看到在块内是不能写外部i变量的,除非用__block修饰:

#import Foundation/Foundation.h 

int main(int argc,char *argv[])

 @autoreleasepool{

 __block int i = 10;

 //foo是一个块变量被赋值为一个块。

 int (^foo)(int) = ^(int x) {

 i = 100;

 int ret = x * i;

 NSLog(@"%d * i(%d) = %d",x,i,ret);

 return ret;

 i = 1000;

 NSLog(@"ret is %d",foo(11)); //i此时为100哦。

 return 0;


如果是在ruby中则外部变量变化会导致block的结果发生变化,也给个例子吧:

apple@kissAir: objc_src$irb

2.1.1 :001 $v = 100

 = 100 

2.1.1 :002 b = - (x){puts "#$v * #{x} = #{$v * x}"} 

 = # Proc:0x0000010182c0d8@(irb):2 (lambda) 

2.1.1 :003 b[11]

100 * 11 = 1100

 = nil 

2.1.1 :004 $v=11

 = 11 

2.1.1 :005 b[11]

11 * 11 = 121

 = nil 


[2014.07.06第一次新增内容]:块功能扩展

我们还可以用block来实现集合对象的map功能,比如ruby中数组或散列的map:

#import Foundation/Foundation.h 

#define msg(...) NSLog(__VA_ARGS__)

NSArray *map(NSArray *ary,id (^block)(id))

 NSMutableArray *ary_ret = [NSMutableArray array];

 for(id x in ary)

 [ary_ret addObject:block(x)];

 return ary_ret;

int main(int argc,char *argv[])

 @autoreleasepool{

 NSArray *ary_init = [NSArray arrayWithObjects:@"big",@"small",\

 @"love",@"pluck",@"save",nil];

 NSArray *ary = map(ary_init,^(id item){\

 return [item capitalizedString];});

 msg(@"%@",ary);

 return 0;

}

运行结果如下:

apple@kissAir: objc_src$./blk

2014-07-06 14:47:57.758 blk[1009:507] (

    Big,

    Small,

    Love,

    Pluck,

    Save

)

块能做的事可不止这些哦,我们可以借助GCD中对块的支持并发的执行任务:

#import Foundation/Foundation.h 

#define msg(...) NSLog(__VA_ARGS__)

int main(int argc,char *argv[])

 @autoreleasepool{

 NSMutableArray *ary_m = [NSMutableArray array];

 //获取GCD全局队列

 dispatch_queue_t g_queue = dispatch_get_global_queue(0,0);

 //创建新的执行组

 dispatch_group_t grp = dispatch_group_create();

 srand(time(NULL));

 __block int s = 0;

 for(int i = 0;i 1000;++i){

 dispatch_block_t block = ^{

 s = rand() % 5;

 sleep(s);

 msg(@"at %4d:sleeped %d s",i,s);

 //在组中异步执行块

 dispatch_group_async(grp,g_queue,block);

 //等待组中所有块任务执行完毕

 dispatch_group_wait(grp,DISPATCH_TIME_FOREVER);

 return 0;

}

运行如下:

apple@kissAir: objc_src$./blk

2014-07-06 15:25:07.318 blk[1231:3903] at   19:sleeped 0 s

2014-07-06 15:25:07.318 blk[1231:3303] at   17:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4703] at   21:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4c03] at   22:sleeped 0 s

2014-07-06 15:25:07.319 blk[1231:4003] at   20:sleeped 0 s

2014-07-06 15:25:07.322 blk[1231:3e03] at   31:sleeped 0 s

2014-07-06 15:25:07.323 blk[1231:5e03] at   36:sleeped 0 s

2014-07-06 15:25:07.324 blk[1231:6403] at   40:sleeped 0 s

2014-07-06 15:25:07.325 blk[1231:6803] at   43:sleeped 0 s

2014-07-06 15:25:07.327 blk[1231:7a03] at   53:sleeped 0 s

2014-07-06 15:25:07.328 blk[1231:7a03] at   56:sleeped 0 s

2014-07-06 15:25:07.328 blk[1231:7a03] at   58:sleeped 2 s

2014-07-06 15:25:07.330 blk[1231:8a03] at   64:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   75:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   77:sleeped 0 s

2014-07-06 15:25:07.333 blk[1231:9e03] at   78:sleeped 0 s

2014-07-06 15:25:08.315 blk[1231:1903] at    4:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1103] at    1:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1503] at    3:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:1f03] at    7:sleeped 2 s

2014-07-06 15:25:08.315 blk[1231:2303] at    9:sleeped 2 s

2014-07-06 15:25:08.317 blk[1231:2f03] at   15:sleeped 2 s

2014-07-06 15:25:08.319 blk[1231:2303] at   84:sleeped 0 s

2014-07-06 15:25:08.323 blk[1231:4c03] at   28:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5203] at   30:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5803] at   32:sleeped 2 s

2014-07-06 15:25:08.323 blk[1231:5c03] at   35:sleeped 2 s

2014-07-06 15:25:08.324 blk[1231:5e03] at   38:sleeped 2 s

2014-07-06 15:25:08.324 blk[1231:6603] at   41:sleeped 2 s

2014-07-06 15:25:08.325 blk[1231:5203] at   88:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:6a03] at   44:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:5c03] at   90:sleeped 0 s

2014-07-06 15:25:08.325 blk[1231:6c03] at   46:sleeped 0 s

2014-07-06 15:25:08.326 blk[1231:7003] at   48:sleeped 1 s

2014-07-06 15:25:08.327 blk[1231:6a03] at   94:sleeped 0 s

2014-07-06 15:25:08.328 blk[1231:5c03] at   97:sleeped 0 s

2014-07-06 15:25:08.328 blk[1231:5c03] at   99:sleeped 0 s

2014-07-06 15:25:08.329 blk[1231:7a03] at   61:sleeped 3 s

2014-07-06 15:25:08.330 blk[1231:8c03] at   65:sleeped 3 s

2014-07-06 15:25:08.331 blk[1231:8c03] at  102:sleeped 0 s

2014-07-06 15:25:08.333 blk[1231:a003] at   76:sleeped 4 s

2014-07-06 15:25:08.333 blk[1231:9a03] at   73:sleeped 4 s

2014-07-06 15:25:08.334 blk[1231:9a03] at  105:sleeped 0 s



[ CALL指令有多少种写法 ] 之读书笔记 原文为360的安全专家很久之前的一篇文章,偶然发现后收获不少。特以笔记的形式记录下来, 便于加深理解。 Intel有公开的指令集格式文档,你需要的是第二卷的上半部分,指令集从A到M。这篇文档的难度超出一般人想象,里面有众多晦涩的标识、与硬件紧密相关的介绍,拿到这后,即使直接翻到目录的CALL 指令一节,也不见得能够弄清楚。
今日学习解析json字符串,用到了一个eval()方法,解析字符串的时候为什么需要加上括号呢?摸不着头脑。原来javascript中{}语句块具有二义性,不加括号会出错,理解这种二义性对我们理解javascript代码有极大帮助。
读书笔记 effective c++ Item 17 使用单独语句将new出来的对象放入智能指针 1. 可能会出现资源泄漏的一种用法 假设我们有一个获取进程优先权的函数,还有一个在动态分配的Widget对象上根据进程优先权进行一些操作的函数: 1 int priority(); 3 void processWidget(std::tr1::shared_ptr pw, int priority); 注意这里使用了对象管理资源的用法(Item 13),processWidget为它需要处理的动态分配对象Widget使用了智能指针(tr1::shared_ptr)。