iOS:在方法中包装异步调用

时间:2014-02-27 21:08:10

标签: ios objective-c asynchronous

我一直想知道以下情况是否可行:

给定函数foo定义为

- (void)foo:(int)n action:(SEL)selector
{
    // do something, maybe fetching data from server
    ...
    // at a later point
    [self performSelector:@selector(selector) withObject:returnObject];
}

注意foo是一个发给您的黑盒子功能。它无论如何都无法改变


通常会创建函数bar

- (id)bar:(id)x
{
    return x;
}

并致电[self foo:n action:@selector(bar:)]以获得函数bar;

中的结果

相反,我想知道是否可以包装该函数并使其同步,以便我只需要调用

- (id)foobar:(int)n;

获取通常由bar

返回的返回值

4 个答案:

答案 0 :(得分:1)

一种方法是使用no-op选择器调用foo:action:,该选择器保存在实例变量中传递给它的任何对象,然后手动调用bar:

- (void)saveAsIvar:(id)var
{
    _returnObject = var;
    [_fooLock unlock];
}

- (id)bar:(id)x { return whatever; }

- (id)foobar:(int)n
{
    [_fooLock lock];
    [self foo:n action:@selector(saveAsIvar:)]
    while (YES) {
        if ([_fooLock tryLock]) {
            return [self bar:_returnObject];
        }
    }
}

答案 1 :(得分:1)

你正在努力的是foo是有缺陷的。它不应该掉落bar的结果。 foo调用(bar)的选择器应该执行完成代码。

如果你想用foo编写这个工作,你将不得不做一些相当严重的黑客攻击和削减。

我会:

让foo在完成后发布通知,并将结果放入通知的用户词典中。

让foobar完成一个块。让它注册一个通知监听器,它将结果值从通知的用户信息字典中取出并传递给完成块。

答案 2 :(得分:0)

如果我理解正确,您正在尝试创建动态函数名称。所以例如我有一个方法 - (void)fizz:(id)x然后我会调用 - (id)foofizz:(int)n

虽然我没有尝试过,但听起来不是一个好主意,但可以通过使用消息转发来实现 https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html

答案 3 :(得分:0)

在目标c中实现这一点的通常方法是使用块,这些块基本上是像函数指针一样传递的代码块。您将添加一个块作为foo方法的参数。当foo完成其工作时,它应该调用传递给它的块,允许任何客户端在完成foo时执行工作。

在你的.h:

- (void)foo:(int)n withCompletion:(void (^)(id fooResult))completion;

在你的.m

- (void)foo:(int)n withCompletion:(void (^)(id fooResult))completion {

   //do foo stuff

   //invoke the completion block with the result of foo

   if (completion) {
       completion(someResult);
   }
}

现在在你的客户端类中(即,谁试图使用foo)。像这样打电话给foo:

[someObject foo:someInt withCompletion:^(id fooResult) {

    [self bar:fooResult];
}];

这里客户端调用foo并指定在完成时要做什么,在这种情况下,调用bar的结果为foo。

以下是Apple docs,您可以在其中了解有关Objective-C块的更多信息。