Вопрос по cocoa, iphone – Загрузка нескольких файлов в приложении iphone (Цель c)

4

В моем приложении для iPhone я хочу загрузить несколько файлов, которые находятся на IIS с аутентификацией. По нажатию кнопки я хочу начать процесс загрузки.

Я знаю, как скачать файл с аутентификацией.

    NSURLRequest* request =
               [NSURLRequest requestWithURL:mMovieURL 
                             cachePolicy:NSURLRequestUseProtocolCachePolicy 
                             timeoutInterval:60.0];
    movieConnection =
            [[NSURLConnection alloc] initWithRequest:request delegate:self ];

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

Но как это сделать с одновременной загрузкой?

Спасибо,

Ваш Ответ

5   ответов
1

I'm not familiar with MultipleDownload, but in case it doesn't meet your needs, the issue I take it is that you have a single object that is the delegate to many NSURLConnections, and you want to know how to keep them straight.

The delegate methods all return the NSURLConnection itself as their first parameter. So you can keep track of which data goes where by testing which NSURLConnection is calling you back. One way to do this is with an NSDictionary that maps the connection to its NSMutableData object. Now the trick is that you can't make an NSURLConnection be the key in a dictionary because it doesn't conform to NSCopying (and you wouldn't want it to). One way to work around this is to use the address of the connection such as:

NSString *key = [NSString stringWithFormat:@"%p", connection];

Лучшим способом было бы использоватьNSValue сvalueWithNonretainedObject конструктор. Таким образом, вы можете получить доступ к ключевому объекту изNSDictionary если вам нужно.

2

Я думаю, что самый простой способ сделать это - использовать NSOperation - и NSOperationQueue.

Это будет означать, что вы можете указать, должна ли каждая операция выполняться последовательно или параллельно. Вы можете даже ограничить количество параллельных операций - так, чтобы одновременно выполнялось максимум 5 (скажем) операций, а затем другие операции выстраивались в очередь.

Это действительно отличный способ позволить ОС выполнять несколько операций - и хорошо сочетается с ленивой философией загрузки iPhone OS.

После этого вы можете заставить каждую операцию выполнить обратный вызов по окончании - или даже выполнить обратный вызов прогресса в главном потоке.

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

Я не думаю, что это правильно - я думаю, что в этом весь смысл NSOperation
Проблема в том, что nsoperation не может обработать асинхронную загрузку, которая закончится позже, а не сразу.
7

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

Все методы делегата возвращаютNSURLConnection сам как их первый параметр. Таким образом, вы можете отслеживать, какие данные куда идут, тестируя какиеNSURLConnection перезванивает. Один из способов сделать это сNSDictionary который отображает соединение с егоNSMutableData объект. Теперь дело в том, что вы не можете сделатьNSURLConnection быть ключом в словаре, поскольку он не соответствуетNSCopying (и вы бы этого не хотели). Один из способов обойти это - использовать адрес соединения, такой как:

NSString *key = [NSString stringWithFormat:@"%p", connection];

Это вернет уникальный ключ для любого объекта (шестнадцатеричное представление его адреса). Некоторые люди используютdescription для этой цели, но мне это не нравится, потому что это не очень хорошо определенный интерфейс. Нет никаких обещаний, что он будет уникальным. В системах, где я делаю это много, я реализую выше-stringWithFormat: в методе под названием-uniqueIdentifier и сделать его категориейNSObject так что все можно отслеживать в словаре.

Я часто нахожу, что проще создать небольшой объект-обертку, чтобы каждый объект управлял своим собственнымNSURLConnectionнасколько я уверенMultipleDownload делает, но все же эта техника полезна во многих случаях, независимо от того, управляете ли вы несколькими табличными представлениями или чем-то еще, у кого есть делегат.

EDIT: Replaced %x I had above with %p as noted by Peter. He's right, and I wasn't thinking correctly. Double-checking my code, I actually have been using %p, having run into this error before....

Используйте% p для указателей, а не% x. % x - это unsigned int, и указатель не гарантируется того же размера, что и int (действительно, в 64-разрядных версиях Mac OS X онis not одинакового размера).
Исправлена. Благодарю. Вы абсолютно правы.
Теперь вы можете использоватьNSMapTable использовать произвольные объекты в качестве ключей. Из документов: «Его ключи или значения могут быть скопированы на входе или могут использовать идентичность указателя для равенства и хэширования». Это устраняет необходимость в ключевом объекте в этом объяснении.
0

NSURLConnection асинхронный иinit выходит немедленно. Просто запустите его несколько раз.

NSArray *connections = [[NSArray alloc] initWithObjects:
  [[NSURLConnection alloc] initWithRequest:request1 delegate:self ],
  [[NSURLConnection alloc] initWithRequest:request2 delegate:self ],
  [[NSURLConnection alloc] initWithRequest:request3 delegate:self ],
  [[NSURLConnection alloc] initWithRequest:request4 delegate:self ],
  nil];
Я не знаю. Что делать, если ошибка происходит с одним из файлов. Что делать, если один из них занимает много дольше, чем другие. Как вы отслеживаете, когда они все сделали?
6

Я делал это раньше, когда мне нужно было загрузить 10 файлов XML одновременно (это было намного быстрее, чем помещать их в очередь для загрузки одного за другим). Я использовал библиотеки, найденные здесь:

http://github.com/leonho/iphone-libs/tree/master

Их было легко реализовать, и на первой странице приведен пример кода для начала работы.

self.urls = [NSMutableArray arrayWithObjects:
    @"http://maps.google.com/maps/geo?output=json&q=Lai+Chi+Kok,Hong+Kong",
    @"http://maps.google.com/maps/geo?output=json&q=Central,Hong+Kong",
    @"http://maps.google.com/maps/geo?output=json&q=Wan+Chai,Hong+Kong",
    nil];

self.downloads = [[MultipleDownload alloc] initWithUrls: urls];
self.downloads.delegate = self;

Удачи.

Похожие вопросы