#objective-c #cocoa #macos
#objective-c #cocoa #macos
Вопрос:
Чтобы использовать асинхронные http-запросы в objective c, вам необходимо задать делегату значение NSURLConnection
. Проблема в том, что мне нужно выполнить несколько http-запросов, поэтому использование одного и того же делегата (self) не сработает.
Каков наилучший способ сделать это? Должен ли я создавать новый класс делегата для каждого http-запроса? Являются ли эти делегаты просто NSObjects?
Ответ №1:
У вас есть несколько вариантов. Два наиболее распространенных:
-
Создайте новый класс для каждого соединения (да, подкласс
NSObject
) и задайте их в качестве делегатов — пусть они выполняют любую логику, которая вам нужна, при загрузке данных -
Установите один класс в качестве делегата и сохраните ссылки на все ваши
NSURLConnection
классы. Таким образом, когда ваш делегат будет- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
вызван, вы сможете проверить, какойNSURLConnection
используется (например,if ([connection == myConnection])
— или любой другой метод делегирования, который вы реализуете)
Ответ №2:
Что я делаю, так это создаю класс, который будет обрабатывать загрузку файла и уведомлять меня, когда это будет сделано, через селектор. Я передаю ему делегат, селектор и информацию, необходимую для выполнения загрузки.
- (void) downloadFileFrom:(NSString*) httpLocation respondAt:(SEL)selector on:(id)target withParam:(id)param
{
self.finishSelector = selector;
self.delegate = target;
self.responseParams = param;
}
класс является собственным делегатом NSURLConnection. Таким образом, экземпляр отделен от других, которые я могу создавать, И он обрабатывает создание собственного результата для моей работы. Я держусь за объект param. которое может быть чем угодно.
В конце загрузки он выполняет performSelector: для делегата. передача самого себя делегату.
if ([self.target respondsToSelector:self.selector])
{
[self.target performSelector:self.selector withObject:self.param];
}
затем вы можете создать экземпляр загрузчика и вызвать свой метод … сообщив ему, где вам ответить.
MyDownloader downloader = [[MyDownloader alloc] init];
[downloader downloadFileFrom:@"http://www.mydomain.com/myimage" respondAt:@selector(myFileIsComplete:) on:self withParam: downloader];
[downloader autorelease];
другой вариант — создать @protocol для вашего класса, на который он будет отвечать, и заставить вас делегировать в соответствии с ответчиком.
Ответ №3:
Это должно сработать, но есть другой вариант, который следует рассмотреть. Вы могли бы создать универсальный класс, который создает и вызывает NSURLConnection
при условии, что они достаточно распространены. Затем сохраните NSArray
или NSDictionary
один из классов. По одному для каждого соединения.
Пример: У меня есть приложение, которому необходимо загружать несколько фотографий одновременно. Следовательно, у меня есть GetFlickrPhoto
класс. У него есть пользовательский метод инициализации, который получает URL-адрес и любую другую необходимую информацию. Каждый отдельный класс создает NSURLConnection
и может безопасно устанавливать делегат на self
Это помогает сохранять вещи сдержанными и очень управляемыми / повторно используемыми.
Чтобы сделать еще один шаг вперед:
Приложению, о котором я упоминал ранее, также требовалось загружать каналы в формате JSON. Итак, я создал GenericDownload
класс, который принимал URL-адрес и асинхронно загружал NSData
, а затем возвращал NSData
вызывающему делегату через определенные протоколы успеха / неудачи. Ему было все равно, что NSData
содержится.
Я переделал, GetFlickrPhoto
чтобы вызвать GenericDownload
и использовать возвращенное NSData
значение для фотографии. Затем я создал GetJSON
класс, который также вызывал GenericDownload
и анализировал возвращенный NSData
файл в формате JSON.
Это займет немного больше времени, но в итоге вы будете рады обслуживанию и будущим проектам.