2011-11-17 51 views
4

由於不幸中斷了該項目的工作,我正在將我的應用程序例程從ASIHTTP轉換爲AFNetworking ...以及後來發現的AFNetworking的更好更小的代碼庫。從ASIHTTPRequest轉換到AFNetworking

我在找幾個問題。我的ASIHTTPRequest代碼是作爲一種方法構建的。此方法需要幾個參數並將參數發佈到url ...返回結果數據。這些數據總是文本,但爲了製作一個通用的方法,有時可能是json,有時是XML或有時是HTML。因此,我將此方法構建爲獨立的通用URL下載器。

我的問題是,當例程被稱爲我等待響應。我知道所有的「同步是壞的」論點......我不這麼做......但是對於一些我想同步的方法。

所以,這是我的問題。我的簡化ASIHTTP代碼如下,其次是我可以考慮在AFNetworking中編碼的唯一方法。我遇到的問題是AFNetworking在返回該方法之前有時不會響應該響應。 @mattt給出的提示[operation waitUntilFinished]完全無法保持線程,直到調用完成塊...並且我的其他方法[queue waitUntilAllOperationsAreFinished]不一定總是能夠工作(並且不會導致觸發[operation hasAcceptableStatusCode ]條款)。所以,如果任何人都可以提供幫助,那麼請不要猶豫不決地「異步設計」。

ASIHTTP版本:

- (NSString *) queryChatSystem:(NSMutableDictionary *) theDict 
{ 
    NSString *response = [NSString stringWithString:@""]; 
    NSString *theUrlString = [NSString stringWithFormat:@"%@%@",kDataDomain,kPathToChatScript]; 

    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:theUrlString]]; 
    for (id key in theDict) 
    { 
     [request setPostValue:[theDict objectForKey:key] forKey:key]; 
    } 

    [request setNumberOfTimesToRetryOnTimeout:3]; 
    [request setAllowCompressedResponse:YES]; 
    [request startSynchronous]; 

    NSError *error = [request error]; 
    if (! error) 
    { 
     response = [request responseString]; 
    } 

    return response; 
} 

AFNetworking版本

- (NSString *) af_queryChatSystem:(NSMutableDictionary *) theDict 
{ 
    NSMutableDictionary *theParams = [NSMutableDictionary dictionaryWithCapacity:1]; 

    for (id key in theDict) 
    { 
     [theParams setObject:[theDict objectForKey:key] forKey:key]; 
    } 


    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:kDataDomain]]; 

    NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:[NSString stringWithFormat:@"/%@",kPathToChatScript] parameters:theParams]; 


    __block NSString *responseString = [NSString stringWithString:@""]; 

    AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:theRequest] autorelease]; 

    operation.completionBlock =^{ 
     if ([operation hasAcceptableStatusCode]) { 
      responseString = [operation responseString]; 
      NSLog(@"hasAcceptableStatusCode: %@",responseString); 
     } 
     else 
     { 
      NSLog(@"[Error]: (%@ %@) %@", [operation.request HTTPMethod], [[operation.request URL] relativePath], operation.error); 
     } 
    }; 

    NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; 
    [queue addOperation:operation]; 
    [queue waitUntilAllOperationsAreFinished]; 
    [httpClient release]; 


    return responseString; 

} 

非常感謝您的任何想法。

回答

3
- (void)af_queryChatSystem:(NSMutableDictionary *) theDict block:(void (^)(NSString *string))block { 
... 
} 

現在completionBlock內做到:

block(operation.responseString); 

塊將充當委託的操作。除去

-waitUntilAllOperationsAreFinished 

return responseString 

你叫這個名字:

[YourInstance af_queryChatSystem:Dict block:^(NSString *string) { 
    // use string here 
}]; 

希望它能幫助。您可以參考iOS示例AFNetworking有

+0

是的,它的確如此。非常感謝你。我將不得不更多地瞭解塊以開始更多地使用它們。 – Jann

1

我強烈建議使用此機會轉換爲Apple自己的NSURLConnection,而不是採用另一個第三方API。通過這種方式,您可以確定它不會停止。我發現實現它的額外工作是最小 - 但事實證明它更健壯,更不容易出錯。

+0

謝謝,但正如我所說,我寧願在這一點上,使用AFNetworking。 – Jann

+0

我發現你的觀點在你放棄第三方庫的方式上有些不誠實。 AFNetworking的核心就是你正在提倡的NSURLConnection的NSOperation包裝。爲什麼重蹈覆轍,無視社區積極致力於該圖書館的數百小時工作? – mattt

+1

我明白你的觀點。我的建議是基於個人經驗。絕不是不屑一顧。使用Apple示例提供的代碼,我從不需要更多的代碼。許多圖書館提供簡化,但開發人員仍然需要閱讀API文檔,而不是Apple的文檔,這是一個值得懷疑的折衷。現在,隨着「數百小時的工作」不再受到支持,我的建議是有效的,並且是真誠的。請考慮取消您的反對票。 – Mundi

0

我的解決方案是手動運行當前線程runloop,直到回調處理完成。

這是我的代碼。

- (void)testRequest 
{ 
    MyHTTPClient* api = [MyHTTPClient sharedInstance]; // subclass of AFHTTPClient 
    NSDictionary* parameters = [NSDictionary dictionary]; // add query parameters to this dict. 
    __block int status = 0; 
    AFJSONRequestOperation* request = [api getPath:@"path/to/test" 
             parameters:parameters 
              success:^(AFHTTPRequestOperation *operation, id responseObject) { 
               // success code 
               status = 1; 
               NSLog(@"succeeded"); 
              } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
               // failure 
               status = 2; 
               NSLog(@"failed"); 
              }]; 
    [api enqueueHTTPRequestOperation:request]; 
    [api.operationQueue waitUntilAllOperationsAreFinished]; 

    while (status == 0) 
    { 

     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
           beforeDate:[NSDate date]]; 
    } 

    STAssertEquals(status, 1, @"success block was executed"); 
}