如何在 Objective-C 中编写 lambda 方法?

Posted

技术标签:

【中文标题】如何在 Objective-C 中编写 lambda 方法?【英文标题】:How to write lambda methods in Objective-C? 【发布时间】:2010-10-30 22:46:07 【问题描述】:

【问题讨论】:

【参考方案1】:

Objective-C 中的 lambda 概念现在被封装为 Blocks 的概念,相当于传递引用函数。当然,可以说在 C 语言中已经有了函数指针的概念。块只是捕获本地状态的一种方式(即可以是闭包)。事实上,块也可以在其他 C 语言中使用(在 Mac 上)——有一个建议是让它们成为标准 C 语法的一部分。

这是一个定义 lambda 以将两个数字相乘的示例:

int (^mult)(int, int) = ^(int a, int b)  return a*b; ;

第一部分声明一个^int(int,int) 类型的变量,然后将其分配给返回其两个参数的倍数的lambda 表达式(又名块)。然后,您可以传递该 fn,在其他地方定义它等;您甚至可以在其他功能中使用它。

这是一个定义函数的示例,当调用该函数时,会返回另一个函数:

multiplyBy = ^(int a)  return ^(int b)  return b*a; ; ;
triple = multiplyBy(3);

请注意,您可以将块与对象类型混合(通常使用id 作为对象类型),并且许多新的 Objective-C 对象数据结构具有某种块级操作。 GCD 也使用块来传递任意事件;但是请注意,GCD 也可以与函数指针一起使用。

【讨论】:

另请注意,块支持已移植到 10.5 和带有似是而非块项目的 iPhone OS。 code.google.com/p/plblocks 注意 Blocks 可以在 ios 4 中使用,无需 Plausible Blocks 项目。 +1 'multiplyBy' AIBlue 的优秀示例,感谢您如此简洁地展示了块的灵活性。 ObjC 块类似于 Smalltalk 块,但不清楚 Objective C 中如何或是否可以定义、实现、传递、接受和调用任意类型的块。 在哪里声明 multiplyBy 的类型?【参考方案2】:

OS X 10.6 引入了块。见AlBlue's answer for examples。

如果您不使用 Snow Leopard,则可以使用各种其他功能获得接近功能组合的东西。

使用 C 函数指针的示例:

void sayHello() 
    NSLog(@"Hello!");


void doSomethingTwice(void (*something)(void)) 
    something();
    something();


int main(void) 
    doSomethingTwice(sayHello);
    return 0;

使用命令模式的示例:

@protocol Command <NSObject>
- (void) doSomething;
@end

@interface SayHello : NSObject <Command> 

@end

@implementation SayHello
- (void) doSomething 
    NSLog(@"Hello!");    

@end

void doSomethingTwice(id<Command> command) 
    [command doSomething];
    [command doSomething];


int main(void) 
    SayHello* sayHello = [[SayHello alloc] init];
    doSomethingTwice(sayHello);
    [sayHello release];
    return 0;

使用选择器的示例:

@interface SaySomething : NSObject 

- (void) sayHello;
@end

@implementation SaySomething
- (void) sayHello 
    NSLog(@"Hello!");    

@end

void doSomethingTwice(id<NSObject> obj, SEL selector) 
    [obj performSelector:selector];
    [obj performSelector:selector];


int main(void) 
    SaySomething* saySomething = [[SaySomething alloc] init];
    doSomethingTwice(saySomething, @selector(sayHello));
    [saySomething release];
    return 0;

【讨论】:

这在之前可能是正确的,但该语言现在确实有块,它允许您定义真正的 lambda 表达式。话虽如此,如上所述,能够传递 @selector()s 是 Objective-C 工具包中非常有用的机制。 -1 用于在新的 10.6 版 OS X 中使用 Apple 的 GCC 时缺少有关块的信息,这是 C、ObjC 和 C++ 中可用的一项核心新功能。 +1 用于提供在某些情况下可能比块更可取的设计模式。【参考方案3】:

我在 NSConference 上听到 André Pang 谈到下一个版本的 Objective-C 将如何引入块。

这应该允许函数式编程。

编辑:自从雪豹发布以来,确实如此。 Objective-C 现在有Blocks。

【讨论】:

以上是关于如何在 Objective-C 中编写 lambda 方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 插件的 Swift 编写的 iOS 部分中使用 Objective-C 框架

如何/在哪里声明用于编写objective-c代码的接口、实现、程序格式中的实例变量?

如何在 Objective-C 控制器中以编程方式加载用 swift 编写的自定义 XIB 视图

如何将 watchOS Swift 目标添加到用 Objective-C 编写的 iOS 应用程序中

如何在 Objective-C 中使用 startMonitoringForRegion 扫描多个区域

如何通过编写 Objective-C 代码来动态更改 Interface Builder xib 文件?