Ответ GCDWebServer с завершением блока, вызванным из другого блока

Я использую GCDWebServer для обмена изображениями с моего iPhone на другие устройства в локальной сети.

Я пытаюсь вызвать GCDWebServerCompletionBlock внутри своего собственного блока, но мое приложение падает без каких-либо журналов, кроме «сигнала SIGABRT» на GCDWebServerConnection:

GWS_DCHECK(_responseMessage == NULL);

Однако, если я верну ответ за пределы своего блока, все будет работать нормально.

Вот мой код:

    -(void)handleMediaRequest:(GCDWebServerRequest *)request completion:(GCDWebServerCompletionBlock)completionBlock {
//...
URLParser *parser = [[URLParser alloc] initWithURLString:url];
      NSString *photoId = [parser valueForVariable:@"id"];

      [[PhotoLibraryManager photoLibraryManager] getPhotoWithId:photoId completionBlock:^(UIImage *image) {

        NSData *data = UIImageJPEGRepresentation(image, 0.70);
        completionBlock([GCDWebServerDataResponse responseWithData:data contentType:@"application/octet-stream"]);

      } failureBlock:^(NSError *error) {
        completionBlock([GCDWebServerDataResponse responseWithStatusCode:404]);
      }];
}

Как вызвать GCDWebServerCompletionBlock внутри моего собственного блока?


person tezqa    schedule 27.10.2016    source источник


Ответы (2)


Вы используете синхронный обработчик, поэтому вы должны вернуть ответ от него, когда функция вернется. Невыполнение этого требования является ошибкой программиста, и поэтому ваше приложение прерывается.

Похоже, вам нужен асинхронный обработчик, который позволяет вам вернуть ответ позже. Дополнительную информацию и примеры см. в разделе «Асинхронные ответы HTTP» GCDWebServer README.

person Pol    schedule 29.10.2016
comment
Нет, это неправильно, я использую асинхронный обработчик. Именно поэтому в сигнатуре метода есть блок завершения. Я использую на верхнем уровне: [сервер addDefaultHandlerForMethod: @GET requestClass: [класс GCDWebServerRequest] asyncProcessBlock: ^ (запрос GCDWebServerRequest*, GCDWebServerCompletionBlock завершениеблок) { __strong typeof(weakSelf)strongSelf = weakSelf; [strongSelf handleMediaRequest: завершение запроса: завершение блока]; }]; - person tezqa; 30.10.2016
comment
Плохо, я слишком быстро прочитал твой код. Можете ли вы добавить в свой вопрос трассировку стека, ведущую к GWS_DCHECK(_responseMessage == NULL);? - person Pol; 01.11.2016

Сбой происходит из-за того, что вы собираете GCDWebServer в режиме отладки, и он сообщает о внутренней несогласованности. Скорее всего, вы звоните completionBlock() более одного раза, что недопустимо. Он должен вызываться один раз и ровно один раз для каждого ответа на каждый запрос.

person Pol    schedule 05.01.2019