2013-04-15 14 views
0

我試圖用CFRunLoopRunInMode()來避免返回[AFHTTPClient getPath:...]完成塊。在AFHTTPClient成功和失敗塊內的CFRunLoopRunInMode()

我的代碼如下所示:

NSLog(@"start"); 
__block BOOL someCondition = NO; 
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://domain.com"]]; 
[client getPath:@"my/path" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 
    NSLog(@"success"); 
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSLog(@"async log"); 
     someCondition = YES; 
    }); 
    while (!someCondition) { 
     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, YES); 
    } 
    NSLog(@"failure"); 
}]; 

我預期的輸出是:

start 
async log 
failure 

而是我只得到:

start 

CFRunLoopRunInMode()返回kCFRunLoopRunHandledSource,但分派隊列從不執行提交的塊。如果我在完成塊之外運行相同的代碼,則輸出如預期。

我想不通爲什麼當從完成塊運行時,調度隊列沒有被處理。

有人可以請說出爲什麼發生這種情況?

+1

這是*完成塊*。第一個塊在HTTP請求操作完成時被調用,第二個塊在請求失敗時被調用。 - 請注意,嘗試*等待直到某個異步操作完成通常是一個壞主意,特別是如果它阻塞主線程和用戶界面。 –

+0

我喜歡住在邊緣;)真的,我真的想知道爲什麼它的行爲如此。 – hectr

回答

1

我不明白爲什麼從完成塊運行時不處理調度隊列。

因爲您沒有「運行」調度隊列(沒有「運行」調度隊列等)。你運行了運行循環。調度隊列是相關的,但是是不同的事情。一次只能在一個串行隊列(如main)上運行一個塊。在塊完成之前,不能安排其他塊。 GCD沒有API來規避這種情況。這通常是一件非常好的事情,因爲它可以確保在runloop操作中不總是存在的隊列操作。

1

AFNetwork的成功和失敗塊都在主隊列中調度,您在失敗塊中寫入的異步塊也在主隊列中調度。

直到故障塊完成,您的GCD同步塊纔會運行。因爲'while'條件永遠不會是錯誤的,所以失敗塊永遠不會完成,永遠不會有機會被執行。