1

我偶尔会遇到这种崩溃,这很难重现:

0   CoreFoundation                  0x39ff73e2 __exceptionPreprocess + 158
1   libobjc.A.dylib                 0x3905095e objc_exception_throw + 26
2   CoreFoundation                  0x39ffaf2c -[NSObject(NSObject) doesNotRecognizeSelector:] + 180
3   CoreFoundation                  0x39ff9648 ___forwarding___ + 388
4   CoreFoundation                  0x39f51204 _CF_forwarding_prep_0 + 20
5   Foundation                      0x32914bec -[NSDictionary(NSKeyValueCoding) valueForKey:] + 28
6   MyAppName                       0x00032112 -[myViewController stopPlayersWithVolume:] (myViewController.m:151)

从这段代码:

- (void)stopPlayersWithVolume:(double)volume
{
    for (NSString *file in players)
    {
        AVAudioPlayer *player = [players valueForKey:file];
        if (player.volume == volume || volume == 0)
            [player stop];
    }
}

players是一个NSMutableDictionary属性,无需访问,self.因为我认为 ARC 不需要它。键是文件名(例如“mysound.mp3”),值是AVAudioPlayer对象。

堆栈跟踪是否说file我传递给的参数[NSMutableDictionary valueForKey]实际上不是一个NSString,因此是无法识别的选择器?它总是NSString在调试器中,正如您所期望的那样,它来自通过字典的快速枚举,但在调试器中永远不会发生崩溃。

我唯一的想法是存在损坏字典的线程问题。上面的代码是由 NSTimer 触发的,但这只是通过运行循环发出的消息,而不是单独的线程,所以我相信不必担心跨线程访问?

任何建议表示赞赏。很抱歉把它扔掉,但我被困住了。

编辑:

播放器字典是viewDidLoad这样分配的:

players = [[NSMutableDictionary alloc] init];

并声明如下:

@property (retain, nonatomic) NSMutableDictionary *players;

并合成如下:

@synthesize players;
4

2 回答 2

1

players当您遍历它们时,您的字典或其内容可能正在被释放。你能打开NSZombies并尝试在调试器中重现崩溃吗?它将为您提供有关正在释放的对象的更多信息。

于 2012-12-14T12:36:36.197 回答
0

分配字典(并设置音频内容)的代码如下所示:

NSError *error = [[NSError alloc] init];
NSArray *names = [fm contentsOfDirectoryAtPath:resourcePath error:&error];
players = [[NSMutableDictionary alloc] init];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];

我一定是从某个地方复制并粘贴了它,因为NSError据我所知,使用 of 是错误的,尽管几乎不可能引起问题。我将代码更改为:

NSArray *names = [fm contentsOfDirectoryAtPath:resourcePath error:nil];
players = [[NSMutableDictionary alloc] init];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];

问题消失了,它出现了。不能 100% 确定,但我可以在 10 次尝试中使用前一个代码重现崩溃,而永远不会使用后者。不知道为什么。

于 2012-12-14T14:49:34.613 回答