2010-12-16 73 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