等待URLConnection块完成

时间:2013-06-10 16:35:27

标签: rest nsurlconnection objective-c-blocks semaphore nsthread

我正在为我的iPad应用程序创建一个REST客户端类。所以我创建了一个BOOL方法,它使用我之前创建的NSURLConnection子类进行登录。

此JWURLConnection具有finishLoading和failWithError操作的块类型属性。

问题是,在完全执行此方法后,URL连接很可能完成(或失败)。 A也不能使用额外的方法来使用performSelector:waitUntilDone:,因为我必须等待连接。

现在我尝试使用普通的C信号量和一个额外的线程(这样信号量只阻止RESTClient线程,而不是URLConnections线程),但我没有成功;该方法开始等待,但整个连接内容被冻结,因此没有来自连接的NSLog。

JWURLConnection在-start方法中自己启动它自己的线程:

- (void)start { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [super start]; }); }

以下是我尝试使用的代码(使用信号量):

- (BOOL)loginWithUsername:(NSString *)uName ansPassword:(NSString *)pWord {
    __block BOOL loginSucceeded = NO;

    dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    JWURLConnection *connection = [JWURLConnection connectionWithPOSTRequestToURL:POSTData:];
    [connection setFinished^(NSData *data) {
        // validate server response and set login variable
        loginSucceeded = YES;

        dispatch_semaphore_signal(sema);
    }];
    [connection setFailed:^(NSError *error) {
        loginSucceeded = NO;
        NSLog(@"Login failed: %@", [error description]);

        dispatch_semaphore_signal(sema);
    }];
    [connection start];

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    // do some more stuff like error handling / reporting here

    return loginSucceeded;
}

我希望你能指引我正确的方向......

1 个答案:

答案 0 :(得分:0)

  

JWURLConnection在-start方法中单独启动它自己的线程:

     

- (void)start { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [super start]; }); }

您需要确保在NSURLConnectionNSRunLoop上安排NSOperationQueue的委托方法。虽然start方法实际上可以处理这个问题 - 给定的代码和您的注释表明它没有;)简而言之,dispatch_async并不保证底层线程有一个运行循环和一个调度队列甚至不保证底层线程始终是相同的。

文档显示如何安排连接。

我建议在主线程上安排连接,并在需要时将其更改为NSOperationQueue

您的loginWithUsername:andPassword:方法将立即返回,因为您调用/调用异步函数/方法。

使用异步模式有点“具有感染力”。一旦开始使用异步编程风格,除非使用阻止当前线程的同步原语,否则无法“删除”它。我建议保持异步风格:

- (void) loginWithUsername:(NSString *)uName 
               andPassword:(NSString *)pWord 
                completion:(void(^)(id result))onCompletion;

后来:

[self loginWithUsername:@"Me" andPassword:@"secret" completion:^(id result) {
    if ([result != [isKindOfError class]]) {
        [self fetchImagesWithURL:url completion: ^(id result) {
             ...    
        }];
    }
}];