Стандартный вступительный комментарий с учетом важности будущего: вклад Apple в проект LLVM предполагает, что iOS 5 будет иметь слабые ссылки на самообнуление.Таким образом, объекты могут содержать ссылки на другие объекты, не имея их, и когда эти объекты освобождаются, все указатели на них магически устанавливаются на nil
.Нам придется дождаться публичного выпуска инструментов разработчика, чтобы выяснить, реализует ли iOS эту функциональность (для этого требуется некоторая поддержка во время выполнения по понятным причинам) и, если да, то использует ли ее Apple для делегатов.Однако это, скорее всего, произойдет довольно скоро, и, как разработчик, вы сможете получить версию инструментов NDA, которая доступна в настоящее время, поэтому, возможно, стоит рассмотреть этот путь к решению в зависимости от других практических аспектов вашего проекта.
Более полезно для здесь и сейчас:
Делегат для NSURLConnection
s является неизменным.Предполагая, что NSURLConnection
созданы задачами на NSOperationQueue
, о которых вы упомянули, вы также можете создавать их на некотором цикле выполнения, отличном от того, который присоединен к основному потоку, что приводит к целому ряду проблем безопасности потоков в миксе.1009 *
Я бы посоветовал сделать следующее:
- убедитесь, что вы подключаете все
NSURLConnection
s к основному циклу выполнения.Для этого вам нужно создать соединения, чтобы они не запускались сразу, используйте scheduleInRunLoop:forMode:
, чтобы назначить [NSRunLoop mainRunLoop]
(и, вероятно, NSDefaultRunLoopMode
), затем запустите их. - одновременно, сохраните список всехсоединения, которые вы начали.Возможно, вы захотите использовать блок
@synchronized
, чтобы добавить его к подходящему NSMutableArray
- , когда объект, назначенный для получения методов делегата, должен быть освобожден, выполнить
waitUntilAllOperationsAreFinished
в очереди операций.а затем отправьте cancel
всем действующим соединениям (например, [self.arrayOfConnections makeObjectsPerformSelector:@selector(cancel)]
)
Гарантируется, что соединения не будут связываться со своими делегатами после получения сообщения cancel
.Вы хотите подождать, пока все операции в очереди не будут завершены, чтобы избежать возможного состояния гонки, из-за которого контроллер представления освобождается, успешно завершив все соединения в какое-то соответствующее время, но еще не завершенная операция затем пытается добавить новое.
Дополнительно, основываясь на обсуждении нашего комментария по вопросу:
NSURLConnection имеет встроенную систему для асинхронного запуска в цикле выполнения.Циклы выполнения - это версия цикла событий Apple, представляющая собой грубый список сообщений для публикации.Таким образом, они позволяют вам использовать один поток для выполнения множества задач, но только если ни одна вещь не блокирует поток.
Apple фактически рекомендует наиболее эффективный (с точки зрения обработки и времени работы от батареи) асинхронный процесс.URL-доступ обеспечивается за счет асинхронного запуска NSURLConnection в главном потоке.Вы можете настроить текущее значение -(void) startConnection
на:
- (BOOL)startRequest
{
// we're going to do all this right here on the main thread, so there's
// no need to package 'request' and 'keyInfo' into a dictionary and create
// an operation
// create the connection
NNSURLConnection* connection = [[NNSURLConnection alloc] initWithRequest:request delegate:self];
if(connection)
{
NSMutableData *requestData = [[NSMutableData alloc] init];
connection.url = [keyInfo URL];
connection.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:keyInfo, kUserInfoKey, requestData, kRequestDataKey, nil];
[connectionsArray addObject:connection];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
// We used initWithRequest:delegate: so the request has already started.
// The connection will now run asynchronously and we can wait for
// delegate messages, which will be delivered via the runloop on this thread
}
Затем поместите все, что вы делали после того, как соединение закончилось, в ваш connectionDidFinishLoading:
:
- (void)connectionDidFinishLoading:(NNSURLConnection *)connection {
if([connectionsArray indexOfObject:connection] != NSNotFound)
{
[connection cancel];
if([delegate conformsToProtocol:@protocol(ManagerDelegate)] && [delegate respondsToSelector:@selector(managerFailed:withKey:errorCode:)]) {
[delegate managerFailed:self withKey:[connection.userInfo objectForKey:kUserInfoKey] errorCode:ManagerErrorCodeTimeout];
if([connectionsArray count] < 1)
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
[connectionsArray removeObject:connection];
}
/* ...and all the other stuff here... */
}
У меня естьПовсюду предполагается, что NNSURLConnection
является подклассом NSURLConnection
, который просто добавляет несколько дополнительных свойств, которые никак не влияют на поведение.