2010-12-16 37 views
2

我正在使用正在进行异步网络调用的代理。响应将被处理并作为参数传递给下一行中的方法。代码插图低于:在主线程上等待,直到完成一个异步过程?

- (MyClass *) performOperations{ 
    ... 
    ... 
    [self callProxyMethodsTarget:self action:@selector(receivedValue:) withObject:anObject]; //making an asynchronous call here 
    return response; 
} 

- (void) receivedValue:(id)response{  ///need this return value from network call to return from performOperartions 
    ... 
    ... 
} 

我的问题是,作为代理方法进行异步网络调用,我不能够及时得到响应返回。

我已经想到了很多事情,比如:

  • 使网络调用同步但这需要大量的返工,并可能引入不可预见的问题
  • 改变返回类型,并通过从receivedValue响应,但不能这样做,因为我的客户已经定义了这些方法的名称和返回类型以及其他平台上的团队使用的是同步调用

我还以为像一个解决方案:

- (MyClass *) performOperations{ 
     ... 
     ... 
     [self callProxyMethodsTarget:self action:@selector(receivedValue:) withObject:anObject]; //making an asynchronous call here 

     ///write a code here to wait until response is received 
     return response; 
    } 

    - (void) receivedValue:(id)response{  ///need this return value from network call to return from performOperartions 
     ... 
     ... 
    } 

但未能如愿。

回答

0

代理方法是否有代表协议,指示其操作已完成?

如果是这样 - 我不知道你的情况,但是如果你控制了代码,那么你可以添加它们 - 然后你可以设置调用对象作为代理方法的委托,调用调用方法结束时的代理方法,并在调用委托方法时继续。

编辑示例代码

很喜欢他们现在这样做,因为第一个你的方法不能工作 - 一个调用代理方法 - 不能返回一个值。无论什么叫它,它可能都需要一个委托协议。

- (void) performOperations { 
    ... 
    if (proxyMethod == nil) { 
     ProxyMethod *proxyMethod = [[ProxyMethod alloc] init]; 
    } 
    [proxyMethod callProxyMethodsTarget:self action:@selector(receivedValue:) withObject:anObject]; //making an asynchronous call here 
} 

//Assuming this the the delegate method from the proxy object 
- (void) receivedValue:(id)response { 
    // Continue with calling thread here 
    // Return information to whatever called performOperations via 
    // a delegate method or a notification 
} 
+0

确定代理方法有委托方法(我声明名称为)receivedValue:表示网络调用已完成。我不明白你在答案中所说的内容,你能否用代码稍微演示一下。您可以将我的代码修改为演示。 – 2010-12-16 06:32:43

+0

问题是在返回类型我的朋友。在我的代码执行操作返回的东西,但在你的代码performOperations有一个void返回类型:( – 2010-12-16 07:28:05

+0

了解,这就是为什么我把'receivedValue'的评论,在那一点上,你将返回值的两种方式之一。第一种选择是向类'performOperations'和'receivedValue'中添加委托协议,将数据发送回调用方,如'[[self perfOpsDelegate] operationSuccessful:YES withResponseValue:response];'。另一个选项是使用NSNotificationCenter通知:调用者观察类似于ProxyDataUpdatedNotification的内容,'receivedValue'在通知的'userInfo'字典中用'response'发送该通知。 – 2010-12-16 22:07:50

2

我假设performOperations不从主线程调用,因为如果是,那么你就有麻烦了。否则,您可以通过用户当前运行循环是这样的:

- (MyClass *) performOperations{ 
    _isValueReceived = NO; 
    ... 
    ... 
    [self callProxyMethodsTarget:self action:@selector(receivedValue:) withObject:anObject]; //making an asynchronous call here 

    // Start with 10ms time boxes 
    NSTimeInterval ti = 0.01; 
    // Wait until delegate did callback 
    while (!_isValueReceived) { 
    NSDate* date = [NSDate dateWithTimeIntervalSinceNow:ti]; 
    // Let the current run-loop do it's magif for one time-box. 
    [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes 
          beforeDate:date]; 
    // Double the time box, for next try, max out at 1000ms. 
    ti = MIN(1.0, ti * 2);  
    } 

    return response; 
} 

- (void) receivedValue:(id)response { 
    ... 
    ... 
    _isValueReceived = YES; 
} 

这就像为你的后台线程的魅力,也正是在GNUstep使用异步I/O是如何实现的分布式对象同步方法调度,所以应该是与Cocoa在内部的做法非常接近。

但是不是在主线程上可以安全地执行,因为UIKit在默认模式下不能安全地重新进入运行循环。

+0

这些方法在主线程中调用,我不能做太多,因为库已经存在为其他平台而建,我必须将它移植到objective-c :( – 2010-12-16 08:52:54

+0

总是有一些东西可以做!所以“liba rary“是同步的,但是不要在主线程中调用”库“。不要直接从主线程调用'performOperations'(我从'tableView:didSelectRowAtIndexPath:'或类似的方法猜测),只需在后台线程上执行一个中间方法来执行对'performOperations'的实际调用。 – PeyloW 2010-12-16 10:11:26

+0

我终于把异步代理转换为同步网络调用:( – 2010-12-17 10:51:51

1

你需要稍微重构你的应用程序。您不能等待结果到达的位置,因为这会阻塞主线程,这意味着运行循环中的事件将不会被服务。这是不好的原因有两个

  1. 用户将体验到锁定应用
  2. 最有可能的异步答复发布到运行的循环作为一个事件。这意味着你永远不会看到它,你将永远被阻止。

您需要为应用程序创建一些状态,例如一个标志proxyRequestMade并在发出请求时进行设置。然后该方法将返回到运行循环而不返回值。

然后,当您收到响应时,您需要处理它并重置标志。你有这个标志的原因是它可能改变你处理其他UI事件的方式,例如请求正在制作时,您可能会禁用某些按钮。

+0

很好的答案:)我很感激它,并希望通知你,我是面对你提到的第二点。现在我的情况是最糟糕的,因为我在制作一个图书馆,需要实时返回回复。可能是其他开发者将在他们的应用程序中使用这个库。所以我没有其他地方可以等待指定的地方:(我已经决定了两个转换代理从现在开始异步调用到同步调用,并把庞然大物下来。不管怎样,感谢你的好信息+1。 – 2010-12-16 09:41:52