1

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

- (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);
}
4

3 回答 3

10

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

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

在任何地方工作,您不必跟踪运行循环或线程。

于 2012-05-10T15:55:55.950 回答
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 都需要存在于线程的范围内,以便执行其关联的任务。

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

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

祝你好运!

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

于 2013-08-13T14:49:16.800 回答
0

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

NSURLResponse* response = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];
于 2012-05-10T15:53:15.000 回答