我偶尔会遇到这种崩溃,这很难再现:
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;
答案 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次尝试中重现崩溃,而从不使用后者。不知道为什么。