AFHTTPSessionManager – получить несериализованный / необработанный ответ (NSData?)

Я подклассифицировал AFHTTPSessionManager в соответствии с рекомендуемой практикой для iOS 8 (вместо AFHTTPOperationManager, который я использовал раньше).

Я могу захватить NSHTTPURLResponse из task (за исключением того, что не имеет тела, только заголовки), и обратный вызов возвращает сериализованный объект responseObject который является прекрасным.

Иногда мне нужно записать ответ в виде строки или отобразить его в текстовом поле – похоже, не существует способа сделать это изначально с помощью SessionManager? OperationManager разрешил вам ссылаться на исходный ответ как на NSString:

 operation.responseString; 

Я предполагаю, что я мог бы стягивать сериализованный requestObject, но это похоже на много лишних накладных расходов и не поможет, если объект ответа недействителен JSON.

Вот мой подклассовый синглтон:

 @implementation MyAFHTTPSessionManager + (instancetype)sharedManager { static id instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance; } 

И затем, чтобы сделать простой GET (который я добавил к блочному методу), я могу сделать:

 [[MyAFHTTPSessionManager sharedManager] GET:_url parameters:queryParams success:^(NSURLSessionDataTask *task, id responseObject) { completion(YES, task, responseObject, nil); } failure:^(NSURLSessionDataTask *task, NSError *error) { completion(NO, task, nil, error); }]; 

Это можно сделать, создав настраиваемый сериализатор ответов, который записывает данные и сериализует ответ, используя стандартный сериализатор ответов, объединяя как необработанные данные, так и анализируемый объект в настраиваемый составной объект ответа.

 @interface ResponseWithRawData : NSObject @property (nonatomic, retain) NSData *data; @property (nonatomic, retain) id object; @end @interface ResponseSerializerWithRawData : NSObject <AFURLResponseSerialization> - (instancetype)initWithForwardingSerializer:(id<AFURLResponseSerialization>)forwardingSerializer; @end ... @implementation ResponseWithRawData @end @interface ResponseSerializerWithRawData () @property (nonatomic, retain) forwardingSerializer; @end @implementation ResponseSerializerWithRawData - (instancetype)initWithForwardingSerializer:(id<AFURLResponseSerialization>)forwardingSerializer { self = [super init]; if (self) { self.forwardingSerializer = forwardingSerializer; } return self; } - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { id object = [self.forwardingSerializer responseObjectForResponse:response data:data error:error]; // TODO: could just log the data here and then return object; so that none of the request handlers have to change if (*error) { // TODO: Create a new NSError object and add the data to the "userInfo" // TODO: OR ignore the error and return the response object with the raw data only return nil; } else { ResponseWithRawData *response = [[ResponseWithRawData alloc] init]; response.data = data; response.object = object; return response; } } @end 

Затем установите этот сериализатор в диспетчере сеансов:

 @implementation MyAFHTTPSessionManager + (instancetype)sharedManager { static id instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; instance.responseSerializer = [[ResponseSerializerWithRawData alloc] initWithForwardingSerializer:instance.responseSerializer]; }); return instance; } 

Теперь в вашем обработчике завершения вы получите экземпляр ResponseWithRawData:

 [[MyAFHTTPSessionManager sharedManager] GET:_url parameters:queryParams success:^(NSURLSessionDataTask *task, id responseObject) { ResponseWithRawData *responseWithRawData = responseObject; NSLog(@"raw data: %@", responseWithRawData.data); // If UTF8 NSLog(@"raw data: %@", [[NSString alloc] initWithData:responseWithRawData.data encoding:NSUTF8StringEncoding]); // TODO: do something with parsed object } failure:^(NSURLSessionDataTask *task, NSError *error) { }]; 

Я просто взбивал это без компиляции / тестирования, поэтому я оставлю его для отладки и заполнения пробелов.

Вы можете получить доступ к объекту «данные» непосредственно из AFNetworking с помощью ключа «AFNetworkingOperationFailingURLResponseDataErrorKey», поэтому нет необходимости подклассифицировать AFJSONResponseSerializer. Вы можете сериализовать данные в читаемый словарь. Вот пример кода для получения данных JSON:

 NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey]; NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil]; 

Вот код для получения кода состояния в блоке Failur

 NSHTTPURLResponse* r = (NSHTTPURLResponse*)task.response; NSLog( @"success: %d", r.statusCode ); 
  • Почему мое событие «прикоснуться внутрь» для моего UIButton не называется?
  • UISearchController searchBar не исчезает, когда push viewcontroller
  • Что произойдет, если для kSecAttrIsPermanent установлено значение НЕТ?
  • Ошибка 1012 при использовании SSL в AFNetworking 2.0
  • Как проверить, имеет ли объект NSMutableArray уже (объект __bridge id) в массиве
  • Внешний вид MFMailComposeViewController setTintColor теряется iOS 7
  • uilongpressgesturerecognizer падает, даже если не реализован
  • как установить локальное уведомление каждые две недели
  • ios 9 и NSAppTransportSecurity
  • Загрузить изображение из пакета с IOS
  • HTML из NSAttributedString
  • Interesting Posts

    Сохранение игрового счета локально на устройстве iOS … нужна безопасность?

    UIRemoteNotificationTypeAlert устарел – как мне перейти на UIUserNotificationTypeAlert с большой командой?

    private vs. fileprivate при объявлении глобальных переменных / констант в Swift3?

    Почему сбой в удалении в iOS 7?

    Swift – Как использовать локализацию из общего расширения

    Удаленные уведомления iOS 10 с фотографиями

    Кордова iOS не может отключить просмотр с клавиатуры

    Как воспроизводить видео с URL-адреса без расширения файла в iOS?

    UIDatePicker с кнопкой «done»

    Как показать HTML-текст из API на iPhone?

    Откажитесь от экрана SCNScene в UIImage

    Каков наилучший способ скопировать раскадровку из одного приложения в другое в ios?

    Как я могу увеличить масштабирование UIScrollview до фиксированной точки?

    Phonegap EmailComposer с приложением для iOS не работает

    Как получить текстовое значение каждой динамически созданной строки в UITableView в swift

    Давайте будем гением компьютера.