NSURLConnection需要NSRunLoop才能执行?

时间:2012-05-10 13:38:33

标签: objective-c nsurlconnection nsrunloop

我正在尝试从名为connect的方法中获取URL的内容。它读取其配置设置并尝试获取URL。它似乎需要运行循环来执行。我虽然只执行一次并完成。似乎除了每次获取此URL时,无论何时调用connect,我都不需要运行该循环。有没有更好的方法呢?

- (BOOL) connect 
{
    // read serverName and eventId from preferences
    NSMutableArray* preferences;
    preferences = [NSMutableDictionary dictionaryWithContentsOfFile:@"/tmp/wt.plist"];

    // if these values aren't nil or blank
    if ([preferences valueForKey:@"serverAddress"] && [preferences valueForKey:@"eventId"]) {

        [self setServerAddress:@"172.16.28.210"];
        [self setEventId:@"OT-3037009"];
    } else{
        // return some kind of error message
    }

    NSLog(@"VideoDataURL: %@", [self getVideoDataURL]);

    // grab the URL and query the server

    NSURL *myURL = [NSURL URLWithString:@"http://localhost"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL
                                                           cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                       timeoutInterval:2];

    __unused NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

    [[NSRunLoop currentRunLoop] run];

    return TRUE;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This method is called when the server has determined that it
    // has enough information to create the NSURLResponse.

    // It can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.

    // receivedData is an instance variable declared elsewhere.
    [incomingData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    /* 
     * Called each time a chunk of data arrives
     */

    NSLog(@"received %lu bytes", [data length]);

    // Create a mutable data if it doesn't already exist
    if (!incomingData) {
        incomingData = [[NSMutableData alloc] init];
    }

    [incomingData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    /*
     * Called if the connection fails
     */

    NSLog(@"connection failed: %@", [error localizedDescription]);  
    incomingData = nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    /*
     * Called when the last chunk has been processed
     */

    NSLog(@"Got it all!");

    NSString *string = [[NSString alloc] initWithData:incomingData encoding: NSUTF8StringEncoding];

    incomingData = nil;

    NSLog(@"response is: %@", string);
}

3 个答案:

答案 0 :(得分:10)

如果您正在从主线程开始连接,是的,这是正确的。我只是使用GCD在主线程上创建并启动连接,以避免考虑运行循环。

dispatch_async(dispatch_get_main_queue(), ^{
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
    [conn start];
});

从任何地方开始工作,您无需跟踪运行循环或线程。

答案 1 :(得分:3)

我会确保你手动告诉runLoop你正在运行连接的工作线程运行,直到连接完成。如果你不这样做,Cocoa会自动让线程进入休眠状态,因此你的委托方法似乎永远不会收到响应。

// The following is delcared within the scope of a NSThread, NSOperation, or GCD Block
//
// The NSURLConnection object and it's initialization/start methods
// |
// V
// Above the method call to the thread's runLoop.
//
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:<a time interval>];
// I use a minute, or 60.0, before I manually cancel the connection
// and send an error message back to the caller.

^生成连接后应该调用的方法。它应该为您提供您正在寻找的结果。

在构建异步服务器调用/任务时,请记住此结构:

RunLoop

任务

每个异步任务都需要自己的RunLoop,以便在事件存在期间连续轮询事件。每个RunLoop都需要存在于线程范围内,以便执行相关的任务。

您可以使用NSThread / NSRunLoop / NSURLConnection,Grand Central Dispatch或甚至NSOperation / NSOperationQueue手动构建异步网络任务。我更喜欢操作/队列,因为我觉得它们更像面向对象,并且基于块的编程可能有点棘手(如果您只是使用“dispatch_”调用,那么您将编写请求的结构)。当一切都归结为它时,根据您的编程偏好编写您的线程模型。每种方法都会给你相同的结果。

此外,除非您正在执行需要同步的任务部分,否则不要使用dispatch_sync,否则您将锁定UI。掌握RunLoops是必要的,以便为您的应用程序创建真正的异步模型。

祝你好运!

P.S。 NSURLConnection已构建为异步运行,但是,要创建真正的异步网络模型,您的应用程序将需要在与主线程分开的线程上生成连接。

答案 2 :(得分:0)

我认为同步请求不需要运行循环:

NSURLResponse* response = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];