4 часа прошло, и я нашел проблему. Я опишу, как я решил проблему в XMLPerformance sample
.
Проблема была в NSAutoreleasePool
. Есть @property (nonatomic, assign) NSAutoreleasePool *downloadAndParsePool;
. Когда приложение начинает загружать Top300 Paid Apps RSS
, создается новая тема с использованием [NSThread detachNewThreadSelector:@selector(downloadAndParse:) toTarget:self withObject:url];
. Таким образом, в этом потоке мы должны хранить локальный пул автоматического выпуска. Это делается следующим образом:
- (void)downloadAndParse:(NSURL *)url {
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
// initializing internet connection and libxml parser.
if (rssConnection != nil) {
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);
}
// Release resources used only in this thread.
[downloadAndParsePool release];
self.downloadAndParsePool = nil;
}
Так что в downloadAndParse:
все выглядит хорошо. Теперь давайте рассмотрим один метод, который вызывается при разборе элемента из RSS:
- (void)finishedCurrentSong {
// sending new item to delegate and other ...
countOfParsedSongs++;
// Periodically purge the autorelease pool. The frequency of this action may need to be tuned according to the
// size of the objects being parsed. The goal is to keep the autorelease pool from growing too large, but
// taking this action too frequently would be wasteful and reduce performance.
if (countOfParsedSongs == kAutoreleasePoolPurgeFrequency) {
[downloadAndParsePool release];
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
countOfParsedSongs = 0;
}
}
Как вы видите там строки:
[downloadAndParsePool release];
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
Так что именно эти строки вызывают исключение. Если я их комментирую, все отлично работает.
Но я решил не только прокомментировать эти строки, но и заменить NSAutoreleasePool
в - (void)downloadAndParse:(NSURL *)url
блоком @autorelease
, так как сказано, что он более эффективен:
- (void)downloadAndParse:(NSURL *)url {
@autoreleasepool {
// initializing internet connection and libxml parser.
if (rssConnection != nil) {
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);
}
// Release resources used only in this thread.
}
}
Теперь все отлично работает. Единственная проблема, которую я не решил:
// Periodically purge the autorelease pool. The frequency of this action may need to be tuned according to the
// size of the objects being parsed. The goal is to keep the autorelease pool from growing too large, but
// taking this action too frequently would be wasteful and reduce performance.
Так что, если у кого-то есть какие-либо мысли по поводу этой проблемы, можно опубликовать еще один ответ и, возможно, попытаться объяснить более правильно исправление ошибки. Я буду рад принять этот ответ.
Спасибо.