2011-12-16 53 views
1

此問題的由來源於對this question的回答。當音頻完成時,訪問navigationController會產生EXC_BAD_ACCESS

我有一系列由自己的ViewControllers管理的謎題。工作流程是這樣的:

UINavigationViewController - >菜單 - 視圖 - 控制器 - >路由 - 視圖 - 控制器 - >隨機選擇拼圖 - 視圖 - 控制器

「路由視圖控制器」隨機選擇一個謎視圖控制器推到堆棧。一旦有人解決了這個難題,我會播放一個「You Win」音頻樣本,然後將視圖控制器從堆棧中彈出。此時,路由視圖控制器隨機選擇下一個難題。這裏是我的播放聲音和彈出拼圖視圖控制器從堆棧代碼:

-(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 *傳遞的事實有關。

請讓我知道我錯了什麼地方,或者在音頻剪輯完成播放後,有更好的方法觸發視圖轉換。提前致謝!

回答

1

我想出了這裏發生了什麼。問題是與「橋」鑄造我在這一行做了:

AudioServicesAddSystemSoundCompletion(soundID, nil, nil, soundFinishedPlaying, (__bridge void *)clientData); 

如果我改變了橋接模式而不是__bridge_retained是保險,我NavigationController的情況下也不會被取消引用,直到聲音完井方法已經完成後, 。通過使用__bridge_retained,這也意味着我必須在soundFinishedPlaying中使用CFRelease(...)顯式取消引用該點。

我還在斜坡上升對蘋果的代碼分析工具,以確認沒有其他的內存泄漏,所以如果我錯過任何細節,在這裏隨意填寫他們進來。

FYI ...感謝this post指向我在正確的方向。