这个问题的起源源于对this question的回答。
我有一系列由他们自己的ViewControllers管理的谜题。工作流程如下所示:
UINavigationViewController - >菜单视图控制器 - >路由视图控制器 - >随机选择的拼图视图控制器
“路由视图控制器”随机选择拼图视图控制器以推入堆栈。一旦有人解决了这个难题,我就会播放一个“You Win”音频样本,然后将视图控制器从堆栈中弹出。此时,Routing View Controller随机选择下一个谜题。这是我播放声音和将拼图视图控制器从堆栈中弹出的代码:
-(void) playSound:(SystemSoundID)soundID withClientData:(UIViewController*)clientData {
soundIsPlaying = true;
if (clientData)
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, soundFinishedPlaying, (__bridge void *)clientData);
else
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, soundFinishedPlaying, nil);
AudioServicesPlaySystemSound(soundID);
}
void soundFinishedPlaying(SystemSoundID ssID, void *clientData)
{
soundIsPlaying = false;
if(clientData) {
NSLog(@"clientData not null!");
UINavigationController * navController = ((__bridge UIViewController *) clientData).navigationController;
if (navController){
NSLog(@"navController not null!");
[navController popViewControllerAnimated:false];
} else {
NSLog(@"NavController was nil!");
}
}
}
问题是在第二个谜题解决之后我在soundFinishedPlaying中的这行代码上抛出了一个EXC_BAD_ACCESS错误:
UINavigationController * navController = ((__bridge UIViewController *) clientData).navigationController;
如果我调试这行代码,我可以看到clientData有一个对UINavigationController的引用,所以我有点困惑为什么我看到这个错误。
我怀疑它可能与我需要为soundFinishedPlaying指定直接C函数和/或我需要在UIViewController引用中作为void *传递的事实有关。
请让我知道我哪里出错了,或者在音频剪辑完成播放后有更好的方法来触发视图转换。提前谢谢!
答案 0 :(得分:1)
我弄清楚这里发生了什么。问题在于我在这条线上所做的“桥梁”铸造:
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, soundFinishedPlaying, (__bridge void *)clientData);
如果我将桥接模式更改为__bridge_retained而确保我的NavigationController实例在声音完成方法完成之后才会被取消引用。通过使用__bridge_retained,这也意味着我必须在soundFinishedPlaying中使用CFRelease(...)显式地取消引用该点。
我仍在使用Apple代码分析工具来确认没有其他内存泄漏,所以如果我错过了任何细节,请随时填写。
仅供参考...感谢this post让我指向正确的方向。