AVFAudio 在 PerformSelector:withObject:finishedPlaying 上崩溃

问题描述 投票:0回答:1

我正在尝试解决此崩溃问题:

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];

蒂亚

ios avplayer avaudioplayer avaudiosession
1个回答
0
投票

好吧,让我分享我的发现(无论多么稀缺),也许它们会对某人有所帮助。我没有在代码中使用 AVAudioPlayer 的委托,但我有一个据称正在播放的声音集合,偶尔我会迭代该集合并删除带有 false

isPlaying
字段的声音。它导致了上面提到的崩溃,尽管这种情况极为罕见。您的情况可能看起来完全不同(就像有一个 AVAudioPlayer 与包含的类一起被删除),但效果可能是相同的。

我所做的更改最终读取了该错误:我制作了 AVAudioPlayerDelegate,它删除了刚刚播放完的声音。

我的理论如下。声音播放代码在另一个线程上运行,当它完成时,它将

isPlaying
设置为 false(或任何导致其返回 false 的结果)并且尝试在 UI 线程上调用委托的
finishedPlaying
,这会带来一些轻微的延迟。现在,如果您在这两个事件之间删除 AVAudioPlayer ,会发生什么,可能会导致尝试访问已删除播放器的
delegate?.finishedPlaying

这只是一个推测性的猜测,但它似乎符合观察到的结果:崩溃、为什么它如此难以重现以及为什么我的更改修复了它。

© www.soinside.com 2019 - 2024. All rights reserved.