aqu*_*lin 5 function block objective-c
当我学习目标C时,我的理解是新的和不完整的.块的概念与函数非常相似.他们甚至看起来几乎相同:
名为'multiply'的FUNCTION
#import <Foundation/Foundation.h>
int multiply (int x, int y)
{
return x * y;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int result = multiply(7, 4); // Result is 28.
NSLog(@"this is the result %u",result);
}
}
Run Code Online (Sandbox Code Playgroud)
BLOCK名为'Multiply'
#import <Foundation/Foundation.h>
int (^Multiply)(int, int) = ^(int num1, int num2) {
return num1 * num2;
};
int main(int argc, char *argv[]) {
@autoreleasepool {
int result = Multiply(7, 4); // Result is 28.
NSLog(@"this is the result %u",result);
}
}
Run Code Online (Sandbox Code Playgroud)
我在网上发现了各种各样的语句:"块被实现为Objective-C对象,除了它们可以放在堆栈上,因此它们不一定必须是malloc(如果你保留对块的引用,但它会被复制到堆上."
Ray Wenderlich说:"块是一流的功能"
我不知道这一切意味着什么.我的例子表明,同样的事情是作为一个块或一个函数完成的.有人可以展示一个例子,哪些块可以做某些功能不能?或相反亦然?或者它是否更微妙,就像在内存中处理变量'result'的方式一样?或者更快/更安全?它们中的任何一个都可以用作类定义中的方法吗?
谢谢.
块是Objective-C对象,而函数则不是.在实践中,这意味着您可以将一块代码传递给另一块代码,如下所示:
NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(@"Hello, %@", name);
}];
Run Code Online (Sandbox Code Playgroud)
在C中,您可以通过传递指向函数的指针来实现类似的效果.然而,执行此操作和使用块之间的主要区别在于块可以捕获值.例如,在上面的示例中,如果我们想使用变量问候语:
NSString *greeting = @"Hello";
NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(@"%@, %@", greeting, name);
}];
Run Code Online (Sandbox Code Playgroud)
在此示例中,编译器可以看到块依赖于局部变量greeting并将"捕获"其值greeting并将其与块一起存储(在这种情况下,这意味着保留并存储指向NSString的指针).无论块最终被使用(在这种情况下,在实现中[NSArray -enumerateObjectsUsingBlock:]),它都可以访问greetings变量,就像在声明块时一样.这使您可以使用块范围内的任何局部变量,而无需担心将它们传递到块中.
要使用C中的函数指针执行相同操作,greeting必须作为变量传入.但是,这不可能发生,因为调用者(在这种情况下,NSArray)无法知道(特别是在编译时)它必须传递给您的函数的确切参数.即使它确实如此,你也需要以某种方式将值传递greeting给NSArray,以及你想要使用的所有其他局部变量,这将很快变得毛茸茸:
void greet(NSString *greeting, NSString *name) {
NSLog(@"%@, %@", greeting, name);
}
// NSArray couldn't actually implement this
NSString *greeting = @"Hello";
NSArray *names = @[@"Bob", @"Alice"];
[names enumerateObjectsUsingFunction:greet withGreeting:greeting];
Run Code Online (Sandbox Code Playgroud)
块是闭包——它们可以从周围范围捕获局部变量。这是块(以及其他现代语言中的匿名函数)和 C 中函数之间的巨大差异。
这是一个高阶函数的示例makeAdder,它创建并返回一个“加法器”,该函数将某个基数添加到其参数中。此基数由参数设置为makeAdder。因此makeAdder可以返回具有不同行为的不同“加法器”:
typedef int (^IntFunc)(int);
IntFunc makeAdder(int x) {
return ^(int y) { return x + y; }
}
IntFunc adder3 = makeAdder(3);
IntFund adder5 = makeAdder(5);
adder3(4); // returns 7
adder5(4); // returns 9
adder3(2); // returns 5
Run Code Online (Sandbox Code Playgroud)
这对于 C 中的函数指针来说是不可能的,因为每个函数指针都必须指向代码中的一个实际函数,其中在编译时有一个固定的数量,并且每个函数的行为在编译时都是固定的。因此makeAdder,不可能像这样根据运行时的值创建几乎无限数量的潜在“加法器” 。相反,您需要创建一个结构来保存状态。
除了类型之外,不从周围范围捕获局部变量的块(如您的示例中)与普通函数没有太大区别。
| 归档时间: |
|
| 查看次数: |
2205 次 |
| 最近记录: |