Соединение NSURL sendAsynchronousRequest Как сохранить ответ?

.h @property (strong) NSString *reply; 

У меня есть следующий метод:

 .m @synthesize reply; - (void)send { [NSURLConnection sendAsynchronousRequest:[self request] queue:[[NSOperationQueue alloc] init] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error) { if (error) { //NSLog(@"Error,%@", [error localizedDescription]); [self setReply: [[NSString alloc] initWithString:[error localizedDescription]]]; } else { //NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]); [self setReply: [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]]; } }]; } 

Теперь я попытался вернуть значение из блока / обработчика, но, видимо, это невозможно (или я еще не понял синтаксис).

Я попытался установить локальную переменную, чтобы получить значение ответа (Data), но он вызывает ошибки.

Единственный способ, которым ошибки не были созданы, – это использование свойства класса. Но когда я пытаюсь прочитать значение [self reply], оно равно null, что заставляет меня думать, что он никогда не устанавливается.

Я понимаю, что функция sendAsync является потоковой и асинхронной, поэтому причина в том, что значение [self reply] равно null, а когда я использую sendSynchronousRequest, я всегда получаю ответ ???

Что я делаю неправильно, и как я могу вернуть значение из completeHandler ???

Редактировать # 1: Мне кажется, что я делаю что-то очень не так. Я отслеживал код, и когда я использовал синхронную отправку, все работало нормально. Используя асинхронный, фактический вызов sendAsynchronousRequest никогда не выполнялся, заставляя меня думать, что поток не вызывается и, следовательно, пустое значение.

Редактировать # 2: я нашел способ обойти это, добавив следующее:

 [NSURLConnection sendAsynchronousRequest:[self request] queue:[NSOperationQueue alloc] init completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error) { if (error) { //NSLog(@"Error,%@", [error localizedDescription]); [self setReply: [[NSString alloc] initWithString:[error localizedDescription]]]; } else { //NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]); [self setReply: [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]]; } }]; [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 2]]; 

Однако я не совсем уверен, что понимаю, как это работает. Я предполагаю, что RunLoop сообщает, что операция async выполняется в течение 2 секунд (я могу проверить, потому что при установке интервала дат на низкое значение я получаю нулевой ответ из-за тестирования с помощью живого сервера). Я не понимаю, когда я просто запускаю RunLoop, он блокирует все навсегда, как будто текущий поток никогда не прерывается.

Избавьтесь от этого runUntilDate и попробуйте использовать [NSOperationQueue mainQueue], посмотрите, не изменит ли это что-либо.

 [NSURLConnection sendAsynchronousRequest:[self request] queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error)... 

Почти через месяц я нашел решение своей проблемы:

  NSURLConnection* _connection = [[NSURLConnection alloc] initWithRequest:[self request] delegate:self startImmediately:NO]; self.port = [NSPort port]; self.runloop = [NSRunLoop currentRunLoop]; [self.runloop addPort:self.port forMode:NSDefaultRunLoopMode]; [_connection scheduleInRunLoop:self.runloop forMode:NSDefaultRunLoopMode]; [_connection start]; while (self.finished != YES ) { [self.runloop runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; } [self.runloop removePort:[self port] forMode:NSDefaultRunLoopMode]; [_connection unscheduleFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

Это помогло мне. Имейте в виду, что я должен был правильно реализовать методы делегирования NSConnection (didReceiveResponse, didReceiveData, didFailWithError, connectionDidFinishLoading). Однако теперь он работает асинхронно, не блокирует пользовательский интерфейс и имеет правильную отчетность об ошибках. Надеюсь, это может помочь кому-то застрять в том же вопросе

Вы должны попытаться использовать ключевое слово __block для объявления вашего ответа свойства

 @property (strong) __block NSString *reply; 

Это ключевое слово делает вашу собственность доступной для записи внутри блока.

РЕДАКТИРОВАТЬ

Предложение для метода, который блокирует основной поток до получения ответа или до истечения времени ожидания запроса:

 //this block is used to define a waiting condition typedef BOOL (^ CheckBlock)(); - (BOOL)waitUntilBlockTrue:(CheckBlock)theBlock orTimeout:(int)timeout { NSDate *waitingStartPoint = [NSDate date]; BOOL stillNeedToWait = YES; while (stillNeedToWait && theBlock()) { stillNeedToWait = ([waitingStartPoint timeIntervalSinceNow]*(-1.0)) < timeout; } return stillNeedToWait; } 

Для вашего примера вы вызываете этот метод с помощью:

 [self waitUntilBlockTrue:^{ //returns YES as long as the method should block return (BOOL)(self.reply == nil); } orTimeout:10]; 
  • Как использовать классы из другой цели для тестов в XCTest
  • Нарисуйте квадраты с Core Graphics или включите pngs?
  • Как не запускать скрипт при запуске определенной схемы?
  • В местоположении пользователя отслеживания IOS в Google Map
  • Не удается экспортировать архив приложений IOS из xcode для развертывания AdHoc
  • Добавление контроллера детского представления и изменение его метки
  • Любые учебники о том, как сделать таблицу лидеров и достижения в cocos2d
  • Интеграция Tesseract в ios7
  • CoreData & Data Protection
  • EXC_BAD_ACCESS при вставке subview? (iPhone)
  • Я пытаюсь запустить свой калькулятор
  • Давайте будем гением компьютера.