过度释放AVAudioPlayer实例

问题描述 投票:2回答:2

真的很难找到这个。生产应用程序间歇性崩溃(约2%的用户)。这是一个纸牌游戏,因此卡上有很多点击。每当你点击一张卡片就会发出声音。崩溃看似随机发生,但我可以通过点击卡片一段时间再现,然后随机它会崩溃。

它不可能可靠地再现,但是在使用Instruments / Zombies的长时间会话之后,我看到Zombie对象是一个AVAudioPlayer对象。这是一个简单的纸牌游戏应用程序(没有使用SK或任何其他游戏框架 - 所有UIKit /正常目标C)。我正在使用AVAudioPlayer非常简单的实现。以下所有细节。

堆栈跟踪:

Crashed: com.apple.main-thread
0  libobjc.A.dylib                0x206270d70 objc_msgSend + 16
1  Foundation                     0x207b3d42c __NSThreadPerformPerform + 336
2  CoreFoundation                 0x20701a0e0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
3  CoreFoundation                 0x20701a060 __CFRunLoopDoSource0 + 88
4  CoreFoundation                 0x207019944 __CFRunLoopDoSources0 + 176
5  CoreFoundation                 0x207014810 __CFRunLoopRun + 1040
6  CoreFoundation                 0x2070140e0 CFRunLoopRunSpecific + 436
7  GraphicsServices               0x20928d584 GSEventRunModal + 100
8  UIKitCore                      0x2343a8c00 UIApplicationMain + 212
9  <app name>                      0x1007930f0 main (main.m:14)
10 libdyld.dylib                  0x206ad2bb4 start + 4

AppDelegate.m didFinishLaunchingWithOptions

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
BOOL success = [[AVAudioSession sharedInstance] setActive:YES error:nil];

ViewController.h

@property (strong, nonatomic) AVAudioPlayer *audioPlayer;

ViewController.m

-(void) playSound:(NSString *) strSoundName {

    NSString *fileName = @"Move_1";
    NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"aif"];
    NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];

    float volume = 0.5;

    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
    [self.audioPlayer setVolume:volume];
    [self.audioPlayer play];
}

AVAudioPlayer参考历史enter image description here

handleTap:::是调用playSound的方法

ios objective-c crash avaudioplayer crashlytics
2个回答
1
投票

你在这里做了很棒的调试工作。大多数人都会受到内存管理/堆损坏错误的困扰,就像这个错误一样。

然而,有一个线索,你需要调查仪器跟踪:僵尸在performSelector呼叫后出现。这让我觉得在performSelector调用的代码中引用了一个指向视图控制器或AVAudioPlayer实例本身的指针。由于此代码在取消分配视图控制器后运行,因此您将获得悬空指针。

对于初学者,我会更仔细地看看handleTap:::正在做什么。你在那里援引performSelector吗?如果是这样,请仔细查看您正在使用的实例。如果没有,请在其他地方审核您对performSelector的使用,以查看是否可以将某个普通指针捕获到您的视图控制器或AVAudioPlayer实例。


0
投票

从来没有能够弄清楚它为什么会随机崩溃。

然而,我们能够通过在AVAudioPlayer中初始化viewDidLoad一次来解决问题,然后在该方法中调用play(而不是每次我们想要播放声音时初始化)。

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