[NSDictionary valueForKey:]中无法识别的选择器崩溃

时间:2012-12-14 12:17:13

标签: iphone objective-c ios

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

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;

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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是错误的,尽管几乎不会引起问题。我将代码更改为:

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次尝试中重现崩溃,而从不使用后者。不知道为什么。