Мне нужно изменить заголовки ответов в NSURLResponse. Это возможно?
Изменяемый NSHTTPURLResponse или NSURLResponse
Ответы (4)
Я только что говорил об этом с другом. Я предлагаю написать подкласс NSURLResponse. Что-то в этом роде:
@interface MyHTTPURLResponse : NSURLResponse { NSDictionary *myDict; }
- (void)setAllHeaderFields:(NSDictionary *)dictionary;
@end
@implementation MyHTTPURLResponse
- (NSDictionary *)allHeaderFields { return myDict ?: [super allHeaderFields]; }
- (void)setAllHeaderFields:(NSDictionary *)dict { if (myDict != dict) { [myDict release]; myDict = [dict retain]; } }
@end
Если вы имеете дело с объектом, которого не создавали, вы можете попробовать использовать object_setClass
, чтобы удалить класс. Однако я не знаю, добавит ли это необходимую переменную экземпляра. Вы также можете использовать objc_setAssociatedObject
и вместо этого поместить все это в категорию, если вы можете поддерживать достаточно новый SDK.
Вы можете прочитать их в NSDictionary с помощью метода allHeaderFields
.
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSDictionary *httpResponseHeaderFields = [httpResponse
allHeaderFields];
Чтобы быть на 100% безопасным, вам нужно обернуть его
if ([response respondsToSelector:@selector(allHeaderFields)]) {... }
У меня была аналогичная проблема. Я хотел изменить поля заголовков ответа http url. Мне это было нужно, потому что я хотел предоставить кешированный URL-ответ для UIWebView и хочу обмануть веб-представление, что срок ответа не истек (т.е. я хотел изменить свойство «Cache-Control» заголовка, но сохранить остальные заголовки). Мое решение состояло в том, чтобы использовать NSKeyedArchiver для кодирования исходного HTTP-ответа и перехвата сериализации с помощью делегата. В
-(id) archiver:(NSKeyedArchiver*) archiver willEncodeObject:(id) object
Я проверяю, является ли объект NSDictionary, и если да, я вернул измененный словарь (т.е. с обновленным заголовком «Cache-Control»). Впоследствии я просто десериализовал сериализованный ответ с помощью NSKeyedUnarchiver. Конечно, вы можете подключиться к разархиватору и изменить заголовки в его делегате.
Обратите внимание, что в iOS 5 Apple добавила
-(id)initWithURL:(NSURL*) url statusCode:(NSInteger) statusCode HTTPVersion:(NSString*) HTTPVersion headerFields:(NSDictionary*) headerFields
которого нет в документации (ошибка документации), но есть в общедоступном API NSHTTPURLResponse
Вы можете это сделать, и вам понадобится NSHTTPURLResponse
, а не NSURLResponse
, потому что в Swift NSURLResponse
можно использовать со многими протоколами, а не только с http
, такими как ftp
, data:
или https
. В результате вы можете вызвать его, чтобы получить информацию о метаданных, такую как ожидаемый тип содержимого, тип MIME и кодировка текста, в то время как NSHTTURLResponse
отвечает за обработку ответов протокола HTTP. Таким образом, именно он управляет заголовками.
Это небольшой код, который управляет ключом заголовка Server
из ответа и печатает значение до и после изменения.
let url = "https://www.google.com"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let response = response {
let nsHTTPURLResponse = response as! NSHTTPURLResponse
var headers = nsHTTPURLResponse.allHeaderFields
print ("The value of the Server header before is: \(headers["Server"]!)")
headers["Server"] = "whatever goes here"
print ("The value of the Server header after is: \(headers["Server"]!)")
}
})
task.resume()