目标C中的闭包定义和用法

时间:2011-03-14 03:50:52

标签: objective-c memory-management closures

我正在尝试编写一个通用函数来启动和结束事件到我的Obj-C(iOS)应用程序中。我正在定义- (void)startEvent:(void (^)())completion。在这个函数的主体中,我采取了一个启动动画的动作。我需要的是在特定时间间隔过去时调用completion

因此,我复制completion并将其分配给全局变量(在类范围内)。

我就是这样做的:

void (^startEventCompletionClosure)();

- (void)startEvent:(void (^)())completion {
    // side note: I have NO access to "complete" closure of - [UIView animateWithDuration:...]
    ...
    [self performSelector:@selector(startEventCompleted) withObject:nil afterDelay:kDealy];
    startEventCompletionClosure = [completion copy];
}

- (void)startEventCompleted {
    startEventCompletionClosure();
    [startEventCompletionClosure release];
}

但是,我有几个问题:

  • 这是处理此问题的更好方法吗?
  • __block是NSObject吗? C声明?
  • 为什么我必须copy呢?是不是只能retain呢?
  • 如果它不是Obj-C对象,为什么我可以按原样拨打[... copy][... retain]

感谢阅读!

3 个答案:

答案 0 :(得分:2)

  

这是处理此问题的更好方法吗?

根据您的用法,您可能希望将其存储为实例变量(除非您确实希望在类之间共享块,因此随时更改所有startEvent:被称为。)

  

__block是NSObject吗? C声明?

这是一个C存储限定符。

  

为什么我要复制它?是不是只能保留它?

你可以保留它,但它可能不会做你想做的事情。在C和Objective-C中,在堆栈上创建块。复制时,它(以及它关闭的任何变量)都会复制到堆中。如果保留它,则它及其变量被复制到堆中。

  

如果它不是Obj-C对象,为什么我可以调用[... copy][... retain]原样?

万。 :)更严重的是,在Objective-C中,块被设计为充当Objective-C对象。 (它类似于您可以在NSStringCFStringRef之间无缝投射的原因 - 这些对象旨在实现这一目标。)

答案 1 :(得分:1)

首先,我们将它们称为“块”,而不是Objective-C中的“闭包”。其次,-performSelector:withObject:afterDelay:是我们在阻止之前使用的东西。这些天你应该使用dispatch_after()。最后,块对象,它们符合NSObject协议。

答案 2 :(得分:0)

UIView现在也有很好的基于块的动画方法......

animateWithDuration:动画: animateWithDuration:动画:完成: animateWithDuration:延迟:选择:动画:完成:

[UIView animateWithDuration:kAnimationDurationTime animations:^{
    // animate some animatable properties
    // do some other stuff
  } completion:^(BOOL finished) {
    // code that you want to run
    //  when the animation has finished
}];

我发现这是一种非常有用的动画制作方法。