iOS5在runMode:beforeDate期间崩溃:

Nek*_*kto 10 exc-bad-access objective-c nsrunloop ios ios5

我的应用程序与iOS5 b7和GM版本的兼容性存在问题.

问题出现在下一行代码中:

do {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);
Run Code Online (Sandbox Code Playgroud)

EXC_BAD_ACCESS在一些迭代之后,应用程序与信号崩溃.

传递的迭代次数是随机的(从2到7).

在iOS4和iOS3上一切都运行良好.

Apple的示例中出现了同样的问题:XMLPerformance Sample.

你怎么看待这件事?

10月12日我的应用程序的数千名用户将升级到iOS5,我不希望我的应用程序在AppStore中出现如此奇怪的错误.

Nek*_*kto 10

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;
}
Run Code Online (Sandbox Code Playgroud)

所以在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如你所见那些线条:

[downloadAndParsePool release];
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
Run Code Online (Sandbox Code Playgroud)

确切地说,这些行会导致异常.如果我评论他们一切都很好.

但我决定不仅评论那些行,而且还用块代替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.
    }
}
Run Code Online (Sandbox Code Playgroud)

现在一切正常.我没有解决的唯一问题是:

// 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.
Run Code Online (Sandbox Code Playgroud)

因此,如果有人对此问题有任何想法可以发布另一个答案,可能会尝试更正确地解释错误修复.我很乐意接受这个答案.

谢谢.