2015-06-14 26 views
0

下面的代碼是爲了更好的理解[NSURLConnection sendAsynchronousRequest:queue:completionHandler]異步請求不會輸入完成塊

裏有completionHandlerNSLog語句,但是當我在XCode中運行這個在main.m從命令行項目,它永遠不會進入completionHandler塊。我試過使用不同的隊列,mainQueuecurrentQueue,但都沒有工作。

我的預感是隊列在請求完成之前被釋放,並且涉及到保留週期。

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
     NSCache *myCache = [[NSCache alloc] init]; 

     NSArray *images = @[ 
     @"http://i.stack.imgur.com/E66qr.png", 
     @"http://www.tiempoyquimera.com/wp-content/uploads/2010/01/Euro-Trash-Girl-2010.jpg", 
     @"http://1.bp.blogspot.com/-Mxd8AB2nbQY/UYCISJiQz3I/AAAAAAAAAH8/Tc43U8aa9dM/s1600/Tarantino10colhans_1460858i.jpg", 
     @"https://awestruckwanderer.files.wordpress.com/2014/02/alan-watts.png", 
     @"http://www.esalen.org/sites/default/files/photo_images/20120201_DELLIS__MG_9612_711.jpg"]; 

     for (NSString *image in images){ 
      NSURL *myURL = [NSURL URLWithString:image]; 
      NSURLRequest *request = [[NSURLRequest alloc] initWithURL:myURL]; 

      NSLog(@"Can handle request %@", @([NSURLConnection canHandleRequest:request])); 
      NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 

      [NSURLConnection sendAsynchronousRequest:request 
               queue:[NSOperationQueue mainQueue] 
            completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
             NSLog(@"In the completion handler"); 
             if (!error) 
             { 
              // save data to cache with url as key 
              NSLog(@"Image Added to Cache"); 
              [myCache setObject:data 
                 forKey:myURL]; 
             } else 
             { 
              NSLog(@"Image Not Added to Cache"); 
             } 
            }]; 
     } 
    } 
    return 0; 
} 

回答

3

我的直覺是在完成請求之前隊列被解除分配和保留週期涉及

不太。保留週期不涉及。涉及持久性。您正在使用main函數執行此操作。它立即退出 - 異步的東西(網絡和後續的回調)是異步的,所以它會遲一些,如果我們有任何持久性。但我們不。 main退出,這意味着整個darned程序被拆除,kaboom,之前有任何網絡的機會,更不用說在聯網後回調完成處理程序。

現在對比一下在現實生活中發生的事情。在真實的iOS應用程序中,main確實不是退出,因爲它調用UIApplicationMain,這會循環直到應用程序終止。

int main(int argc, char *argv[]) 
{ 
    @autoreleasepool { 
     return UIApplicationMain(argc, argv, nil, 
      NSStringFromClass([AppDelegate class])); 
    } 
} 

在該代碼中,UIApplicationMain只是繼續工作,直到它被中止或終止。與此同時,班級和實例也如雨後春筍般涌現,並且堅持下去,因爲UIApplicationMain並沒有停止。例如:

@implementation MyViewController 
- (void) someMethod { 
    // ... 
    [NSURLConnection sendAsynchronousRequest:request 
     queue:[NSOperationQueue mainQueue] 
     completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
      // ... 
    } 
} 
@end 

現在,在某種意義上說,同樣的事情發生了:立即someMethod退出。但我們的程序總體上仍在運行! UIApplicationMain有一個運行循環,該運行循環仍在循環。因此,事情依然存在,所以現在異步材料可能會發生 - 我們可以聯網然後調用回調。

+0

是否有'main'持續足夠長的時間來輸入一個完成塊',或者'main'總是在其中一個'blocks'開始之前終止。 – Idr

+0

您需要一個運行循環。見http://stackoverflow.com/questions/2154600/run-nsrunloop-in-a-cocoa-command-line-program – matt