0

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

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

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

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

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;
}

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

4

1 回答 1

0

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

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

您需要确保 aNSURLConnection的委托方法将安排在 aNSRunLoop或 a上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) {
             ...    
        }];
    }
}];
于 2013-06-10T21:14:44.450 回答