Functional techniques 实用技巧

在技巧性上, Objective-C 确实比不上 Swift ,但还是有一些好用的方法的,比如这三个:makeObjectsPerformSelector, enumerateObjectsUsingBlock, 和filteredArrayUsingPredicate 。

makeObjectsPerformSelector 是用来遍历数组的,它没有返回值。最常见的使用场景类似于移除父级视图下的所有子视图,参考下面这段代码:

[[self.view subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];

后面两个方法相对难一些,让我仔细讲一讲。

Objective-C 里的区块(block)就像 Swift 的里面的闭包一样,两者之间有非常多的共性,而 enumerateObjectsUsingBlock 方法就是为了这个理念所设计的。

还记得这章最开始的那个快速枚举吗?这里我们用 enumerateObjectsUsingBlock 方法来重写一下:

[villains enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL
*stop) {
    NSLog(@"Can the Doctor defeat the %@? Yes he can!", obj);
}];

Objective-C 里的区块(block)语法和 Swift 的闭包写法有很大的区别。

你要把参数名写在 ^ 符号后面,并且用括号把参数括起来。在上面这段代码里,执行命令的语句是 NSLog() ,而这个语句有三个参数 obj, idx, 和 stop。

第一个参数 obj 的数据类型是 id,这个数据类型在 Swift 里对应的是 AnyObject。

第二个参数 idx 是 index 的缩写,它描述的是这个元素在数组中的位置。

最后一个参数 stop 是一个指向布尔值的指针,这个东西乍一看可能觉得很奇怪,为什么不直接用一个布尔值呢?因为这个值是用来确保快速枚举循环顺利进行的,假设这里放一个常规的布尔值,你就可以在 block 内部修改这个值,并且无法从外部观察到这一修改。但如果放的是指针的话,就可以在外部观察到它的值,并且无法在内部修改它。

我们来看下面的例子,我们依然用快速枚举的方法循环了这个数组,但在 weeping angels 这个元素的地方停止了循环。

[villains enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL
*stop) {
    if ([obj isEqualToString:@"Weeping Angels"]) {
        NSLog(@"Can the Doctor defeat the %@? Oh, apparently not.",
obj);
        *stop = true;
    } else {
        NSLog(@"Can the Doctor defeat the %@? Yes he can!", obj);
    }
}];

敲黑板,stop 的意思是「改变它指向的布尔值的指」。

还有一点要注意的是,尽管 obj 的数据类型是 id,也就是 Anyobject,在这里依然可以使用 isEqualToString 方法。

results matching ""

    No results matching ""