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)。
相关文章
- 【逆向知识】反调试-除0异常-编程与逆向
- 鸡啄米:C++编程之十三学习之类与对象,类的声明,成员的访问控制
- PHP Socket编程 之 php实现http服务
- JAVA学习(九):JAVA多线程编程
- 并发编程2-安全的发布对象
- python socket编程
- Linux操作系统下的多线程编程详细解析----条件变量
- 面向接口编程实现不改代码实现Redis单机/集群之间的切换
- 8-3-1python语法基础-并发编程-协程&asyncio&异步
- 8-2-1python语法基础-并发编程-线程-创建线程,线程冲突(锁),线程通信(condition,队列),线程池,定时器
- 深入理解Android网络编程:技术详解与最佳实践
- Database之SQL:SQL在线编程、工作中常用SQL代码实践之查询-SQL问题分析解决思路、高级案例SQL语法拆解(单技巧各自用法详细分类/多技巧组合用法)、经典组合案例实战之详细攻略
- Database之SQL:SQL在线编程、工作中常用SQL代码实践(以语法为导向的增、删、改、查,已基本涵盖所有语法案例)之详细攻略
- DayDayUp之Job:牛客网—算法工程师—剑指offer之66道在线编程(解决思路及其代码)——41~66
- Python编程学习:深度剖析shap.datasets.adult()源码中的X,y和X_display,y_display输出数区别
- 要学量化交易,先学编程,python基本语法与变量
- C、C++面试题:编程实现字符串中字串的查找
- Python编程:查看python语法中的关键字keyword
- 【Groovy】编译时元编程 ( 利用注解进行 AST 语法树转换 | 定义注解并使用 GroovyASTTransformationClass 注明 AST 转换接口 | AST 转换接口实现 )
- 【Groovy】Groovy 语言特点简介 ( 支持 Java 语法 | 支持 Java 虚拟机 | Groovy 语言是动态语言 | Groovy 扩展 JDK | 编译时元编程 )
- JS与ES6高级编程学习笔记(四)——ECMAScript6 新增语法
- CSDN编程挑战——《高斯公式》
- 387集Go语言核心编程培训视频教材整理 | 函数、包和错误处理(四)
- shell编程语法
- 第二章 面向过程的编程——2.3提供默认参数