0

Я создаю класс клиента REST для своего iPad-приложения. Поэтому я создал метод BOOL, который делает логин, используя подкласс NSURLConnection, который я создал ранее.Подождите, пока блок URLConnection завершится

Это JWURLConnection имеет свойства типа блока для операций finishLoading и failWithError.

Проблема заключается в том, что соединение с URL, скорее всего, завершается (или выходит из строя) ПОСЛЕ того, как этот метод полностью выполняется. A не может использовать дополнительный метод для использования performSelector:waitUntilDone:, потому что мне нужно дождаться соединения.

Теперь я попытался использовать простые семафоры С и дополнительный поток (так что семафор блокирует только поток 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; 
} 

Я надеюсь, что вы можете привести мой в правильном направлении ...

+0

Я знаю ... Были не только несколько вопросов, и дискуссии по этой или знакомым темам. Но ни одно из их решений не помогло мне. –

ответ

0

JWURLConnection начинает свою собственную нить сам по себе в -start met корыто:

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

Вы должны убедиться, что методы NSURLConnection «s делегат будет планироваться на NSRunLoop или 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) { 
      ...  
     }]; 
    } 
}];