My hunch is that the queue is being deallocated before the request is completed and that retain cycles are involved
Not quite. Retain cycles are not involved. Persistence is involved. You are doing this in a main
function. It exits immediately - the asynchronous stuff (the networking and the subsequent callback) is asynchronous, so it would come later, if we had any persistence. But we don't. main
exits, and that means that the whole darned program is torn down, kaboom, before there is any opportunity to do any networking, let alone call back into the completion handler after the networking.
Now contrast this with how things happen in real life. In a real iOS app, main
does not exit, because it calls UIApplicationMain
, which loops until the app is terminated.
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}
In that code, UIApplicationMain
just keeps running until it is aborted or otherwise terminated. Meanwhile, classes and instance have sprung to life, and they persist, because UIApplicationMain
does not stop. For example:
@implementation MyViewController
- (void) someMethod {
// ...
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// ...
}
}
@end
Now, in one sense, exactly the same thing happens: someMethod
exits immediately. But our program overall is still running! UIApplicationMain
has a run loop and that run loop is still cycling. Thus, things live on, and so now the asynchronous material can happen - we can network and then call the callback.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…