Создание автономного делегирования в obj-c

#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.

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