实现一个方法,该方法接受一个块作为回调函数

72

我想编写一个类似于这样的方法:

+(void)myMethodWithView:(UIView *)exampleView completion:(void (^)(BOOL finished))completion;

基本上,我已经从Apple的UIView类方法中剥离了语法:

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;

同时期望它像这样被使用:

[myFoo myMethodWithView:self.view completion:^(BOOL finished){
                     NSLog(@"call back success");
                 }];

我的问题是如何实现这个功能?如果有人能够指导我正确的文档,那就太好了,最好提供一个非常基本的示例(或类似的Stack Overflow答案——我找不到)。 我仍然不太了解委托是否是正确的方法!

我已经在实现文件中放了一个大概的示例,但由于找不到信息,它只是猜测。

+ (void)myMethod:(UIView *)exampleView completion:(void (^)(BOOL finished))completion {
    // do stuff

    if (completion) {
        // what sort of syntax goes here? If I've constructed this correctly!
    }

}

我想知道为什么没有人提到这个事实,即在此示例中参数类型中的“finished”是完全不必要的... - funct7
3个回答

85
你可以像调用常规函数一样调用代码块:
BOOL finished = ...;
if (completion) {
    completion(finished);
}

那意味着使用你的示例实现完整的块函数将如下所示:

+ (void)myMethod:(UIView *)exampleView completion:(void (^)(BOOL finished))completion {
    if (completion) {
        completion(finished);
    }
}

1
通常情况下,你不需要复制(或保留)一个块。只有当你期望该块在声明它的作用域销毁后继续使用时,才需要复制。复制将块移到堆上。另外,这是一篇好的文章链接 - http://www.mikeash.com/pyblog/friday-qa-2010-01-15-stack-and-heap-objects-in-objective-c.html。就我而言,我通常会在方法开始时复制传递的块。 - Timur Kuchkarov
当我复制粘贴以下代码时:+ (void)myMethod:(UIView *)exampleView completion:(void (^)(BOOL finished))completion { 如果有完成回调,则执行回调函数。 } - alex440
抱歉,我无法理解这个答案。什么是完成?它是typedef吗?你能添加一个教程吗?谢谢。 - Erhan Demirci
1
@ErhanDemirci,completion 是实际的代码块,在方法签名中定义。(void (^)(BOOL finished))completion 允许调用一个 completion() 方法作为回调函数。请查看苹果文档:https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html。 - Johnathon Sullinger
谢谢@jonhathon。方法如何理解任务已完成? - Erhan Demirci
显示剩余3条评论

5

我强烈建议您阅读这份关于Blocks的内容,以便更好地了解发生了什么。


当我复制粘贴以下代码 + (void)myMethod:(UIView *)exampleView completion:(void (^)(BOOL finished))completion { if (completion) { completion(finished); } } 我会得到 "use of undeclared identifier finished" 的错误提示.... - alex440

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接