Я пытаюсь обновить старую программу Mac OS, которую я написал в ASOC (в основном Applescript, но некоторые объекты ObjC для таких вещей, как доступ к веб-сервису). Я использовал синхронное соединение:Как преобразовать из синхронного в асинхронный NSURLConnection
NSData *resultsData = [NSURLConnection sendSynchronousRequest: req returningResponse: &response error: &err];
Учетные данные сервера были встроены в URL-адрес. Это работало отлично для меня, так как программа действительно не могла продолжать ничего делать, пока данные извлекались. Однако изменение метода аутентификации сервера вынудило изменения в этом приложении. Я пробовал все обычные обходные пути с помощью NSURLCredential, но с этой услугой все еще не работает.
Так что, похоже, мне нужно будет изменить для асинхронного вызова:
[[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:YES];
я эту работу с соответствующими методами делегата, самое главное:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
Хотя я люблю просто использовать некоторую форму петли задержки, чтобы проверить, когда данные закончили загрузку (по сути дела, это снова синхронно), я не нашел способ сделать это, который фактически не блокирует соединение.
Я могу использовать NSTimer ждать данных, прежде чем продолжить:
set theJobListTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0.05, me, "jobListTimerFired:", "", true)
on jobListTimerFired_(theTimer)
(jobListData as list) & count of jobListData
if count of jobListData ≠ 0 then
log "jobListTimerFired_ done"
tell theTimer to invalidate()
setUpJobList(jobListData)
end if
end jobListTimerFired_
но это неуклюжая и не работает, пока я нахожусь в модальном диалоге:
set buttonReturned to current application's NSApp's runModalForWindow_(collectionWindow)
(У меня есть диалоги, которые нужно обновить с результатами вызова веб-службы). Прямо сейчас методы делегата блокируются до тех пор, пока модаль не будет уволен.
Нет ли простого способа эмулировать синхронный вызов с использованием методов async?
Попытка использовать семафор, я изменил код:
- (void) startConnection:(int)reqType :(NSMutableURLRequest *)request {
requestType = [NSNumber numberWithInt:reqType];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// This could be any block that is run asynchronously
void (^myBlock)(void) = ^(void) {
self.connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:YES];
myBlock();
if (self.connection) {
// create an object to hold the received data
self.receivedData = [NSMutableData data];
NSLog(@"connection started %@", requestType);
}
dispatch_time_t timeOut = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC);
dispatch_semaphore_wait(semaphore, timeOut);
dispatch_release(semaphore);
semaphore = NULL;
}
затем в обработчике соединения:
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"connectionDidFinishLoading %@", requestType);
NSString *returnData = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding] ;
// NSLog(@"connectionDidFinishLoading %@", returnData);
[self handleData:requestType :returnData];
[self terminate];
if(semaphore) {
dispatch_semaphore_signal(semaphore);
}
}
Однако обработчик connectionDidFinishLoading (и на то пошло didReceiveResponse и didReceiveData обработчики) не вызывается до истечения 10-секундного тайм-аута отправки. Что мне здесь не хватает?
Так что, кажется, есть та же самая проблема - в «dispatch_semaphore_wait», кажется, блокировать NSURLConnection. Вот что я имею: –