我正在尝试解决此崩溃问题:
Thread 0 Crashed:
0 libobjc.A.dylib 0x0000000180274430 objc_msgSend + 16
1 Foundation 0x0000000181a132e4 __NSThreadPerformPerform + 340 (NSThread.m:1265)
2 CoreFoundation 0x0000000180fbf77c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 (CFRunLoop.c:1982)
3 CoreFoundation 0x0000000180fbf6fc __CFRunLoopDoSource0 + 88 (CFRunLoop.c:2017)
4 CoreFoundation 0x0000000180fbef84 __CFRunLoopDoSources0 + 204 (CFRunLoop.c:2053)
5 CoreFoundation 0x0000000180fbcb5c __CFRunLoopRun + 1048 (CFRunLoop.c:2920)
6 CoreFoundation 0x0000000180edcc58 CFRunLoopRunSpecific + 436 (CFRunLoop.c:3245)
7 GraphicsServices 0x0000000182d88f84 GSEventRunModal + 100 (GSEvent.c:2245)
8 UIKit 0x000000018a6355c4 UIApplicationMain + 236 (UIApplication.m:3956)
经过进一步调查,我发现崩溃发生在 AVFAudio 上: performSelector:withObject:finishedPlaying
我不确定谁调用了这个函数,因为我没有调用这个函数,并且我没有实现 AVAudioPlayer 委托。
我只是在用户点击某物时播放音频。我最初的猜测是音频仍在播放并且视图控制器被关闭。但是,我无法重现它。我播放音频的调用是这样的:
self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[self.audioPlayer play];
当控制器消失时,我称之为:
- (void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.audioPlayer stop];
}
另外,我对 AVAudioPlayer 有强烈的参考
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
不确定这是否会影响它,但我想确保用户即使处于静音状态也能听到声音:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryErr];
[[AVAudioSession sharedInstance] setActive:YES error:&activationErr];
蒂亚
好吧,让我分享我的发现(无论多么稀缺),也许它们会对某人有所帮助。我没有在代码中使用 AVAudioPlayer 的委托,但我有一个据称正在播放的声音集合,偶尔我会迭代该集合并删除带有 false
isPlaying
字段的声音。它导致了上面提到的崩溃,尽管这种情况极为罕见。您的情况可能看起来完全不同(就像有一个 AVAudioPlayer 与包含的类一起被删除),但效果可能是相同的。
我所做的更改最终读取了该错误:我制作了 AVAudioPlayerDelegate,它删除了刚刚播放完的声音。
我的理论如下。声音播放代码在另一个线程上运行,当它完成时,它将
isPlaying
设置为 false(或任何导致其返回 false 的结果)并且尝试在 UI 线程上调用委托的 finishedPlaying
,这会带来一些轻微的延迟。现在,如果您在这两个事件之间删除 AVAudioPlayer ,会发生什么,可能会导致尝试访问已删除播放器的 delegate?.finishedPlaying
。
这只是一个推测性的猜测,但它似乎符合观察到的结果:崩溃、为什么它如此难以重现以及为什么我的更改修复了它。