浅谈XCode编译器的Blocks功能

http://www.robinlu.com/blog/archives/492

Block, 简单的说,就是一个函数对象,和其它类型的对象一样,你可以创建它,可以赋给一个变量,也可以作为函数的参数来传递。计算机科学中,更常用的名字是”closure”或者”lambda”。先通过一个例子看看什么是Block:

    void (^hello)(char*);

    hello = ^(char* str) {
        NSLog(@"hello %s", str);
    };

    hello("robin");

这段代码申明了一个block变量hello,然后用一个block对象为它赋值,最后调用了这个函数。这是打印出的结果:

2009-09-06 16:36:12.693 blocks[6379:903] hello robin

再看一个例子。玩ruby的都知道each方法,可以很方便的遍历一些数据组合。比如:

[1,2,3].each {|x|
  puts x
}

就可以打印出

1
2
3

现在,我们也可以为NSArray加上这样的方法。我为NSArray写了一个Category,加入下面函数的实现:

- (void)each:(void (^)(id))block
{
    for (id obj in self) {
        block(obj);
    }
}

很简单,我们就有了一个属于NSArray的each。看一个调用的例子:


NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil];
[array each:^(id obj) {NSLog(@"hello %@", obj);}];

首先,生成了一个数组对象,里面有三个名字,然后分别向这三个名字说hello。

再来为NSArray实现一个select方法,这个方法为每一个数组中的对象调用block,这个block做出选择,选中的返回true,最后select函数返回一个数组,其中包含所有选中的对象:

- (NSArray *)select:(BOOL (^)(id))block
{
    NSMutableArray *rslt = [NSMutableArray array];
    for (id obj in self) {
        if (block(obj)) {
            [rslt addObject:obj];
        }
    }
    return rslt;
}

再看一个调用的例子:


    NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil];
    [[array select:^(id obj) {
        return [obj isEqualToString:@"robin"];
    }] each:^(id obj) {
        NSLog(@"hello %@ only", obj);
    }];

依然生成包含三个名字的数组,但是先调用select,只选出’robin’,然后只向选出的名字说’hello’。

看到现在,应该已经对block有一个初步的认识了。也许会产生一个疑问,block和函数指针有什么区别?

第一个区别,函数指针是对一个函数地址的引用,这个函数在编译的时候就已经确定了。而block是一个函数对象,是在程序运行过程中产生的。在一个作用域中生成的block对象分配在栈(stack)上,和其他所有分配在栈上的对象一样,离开这个作用域,就不存在了。这是一个Xcode文档中的错误案例:

void dontDoThis() {
    void (^blockArray[3])(void);  // an array of 3 Block references

    for (int i = 0; i < 3; ++i) {
        blockArray[i] = ^{ printf("hello, %d\n", i); };
        // WRONG: Block literal scope is "for loop"
    }
}

另外,block对象在一个作用域中,在这个block之中可以访问同在这个作用域中的本地变量。我们来看一个例子:

void say(NSString *something)
{
    NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil];
    [array each:^(id obj) {
        NSLog(@"%@, %@", something, obj);
    }];
}

这个函数是向数组中的名字说点什么,具体说什么,在block中并不确定. 因为each本身接口的限制,也没法通过函数的参数传入。如果用函数指针来实现,就不可避免的要引入全局或者静态变量,而使用block,则完全没有这个问题。避免使用全局以及静态变量最直接的现实意义就是,更容易写出线程安全的程序。

通常情况下,block对同作用域中本地变量是以只读形式访问的,如果希望以读写方式来访问,需要在申明这个变量时加上__block。

本文的例子放在github上了,其中对NSArray还实现了map和reduce。

如果希望对Blocks做更多的了解,可以参看Xcode中的"Blocks Programming Topics"。

Sublime Text是一个轻量级的编辑器,不同于Xcode这样的完整开发环境,但是你可以使用Sublime Text来编辑代码并配置Xcode编译器来编译运行你的代码。以下是使用Sublime Text与Xcode编译器一起使用的步骤: 1. 首先,确保你已经安装了Xcode开发工具。如果没有安装,请在App Store中搜索并安装Xcode。 2. 打开Sublime Text并创建一个新文件,然后编写你的代码。 3. 保存文件并将其命名为.cpp后缀,以便让Xcode识别为C++代码文件。 4. 按下快捷键Command + B来编译运行你的代码。Sublime Text会调用系统中配置的默认编译器,也就是Xcode编译器。 注意:在使用Sublime Text与Xcode编译器时,你可能需要手动配置Xcode编译器的路径,以确保Sublime Text能够正确调用Xcode编译器。你可以在Sublime Text的设置中搜索"build_systems"并编辑你的编译系统配置文件,添加或修改"cmd"字段,指定Xcode编译器的路径。 希望这个回答能够帮助到你。如果你有任何其他问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [sublime安装及配置教程(C/C++版)](https://blog.csdn.net/qq_39657434/article/details/104703144)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Mac 搭建算法竞赛编程环境 Xcode + Sublime Text 3](https://blog.csdn.net/weixin_42669662/article/details/112132113)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值