12

我想通過AVAudioPlayer播放MP3,我認爲這很簡單。不幸的是,它不是很有效。下面是我所做的:AVAudioPlayer立即停止播放ARC

  • 爲了測試的緣故,我創建了一個新的iOS應用程序(單 視圖)在Xcode。
  • 我加入了AVFoundation框架到項目還有#import <AVFoundation/AVFoundation.h>ViewController.m

  • 我增加了一個MP3文件到Apps的文檔「文件夾。

  • 我改變了ViewControllersviewDidLoad:以下幾點:

代碼:

- (void)viewDidLoad 
{ 
    [super viewDidLoad];   

    NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];  

    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil]; 
    audioPlayer.numberOfLoops = 1; 

    [audioPlayer play]; 

    //[NSThread sleepForTimeInterval:20]; 
} 

不幸的是,音頻明顯停止它開始播放之後。如果我取消對sleepForTimeInterval的評論,它會播放20秒,然後停止播放。只有使用ARC進行編譯時纔會出現此問題,否則,它會完美地工作。

+0

你不需要啓動另一個線程來播放音頻。你有沒有試過提供一個錯誤指針來查看是否有任何東西被記錄? – isaac

+0

你會得到什麼錯誤? – Daniel

+0

是的,我通過一個NSError initWithContensOfURL。它保持零,但...所以我沒有得到任何錯誤,它只是立即停止播放。 – Phlibbo

回答

7

的問題是,與ARC編譯時,您需要確保通過插入release呼叫保持到要永葆因爲編譯器會自動修復「不平衡」 alloc實例的引用(至少在概念上,閱讀Mikes Ash blog post for more details )。您可以通過將實例分配給屬性或實例變量來解決此問題。

在Phlibbo情況下,代碼將被改造成:

- (void)viewDidLoad 
{ 
    [super viewDidLoad];   
    NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];  
    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil]; 
    audioPlayer.numberOfLoops = 1; 
    [audioPlayer play]; 
    [audioPlayer release]; // inserted by ARC 
} 

而且AVAudioPlayer它會立即停止播放當沒有提及離開它被釋放。

我自己並沒有使用ARC,只是簡單地閱讀了一下。如果您對此有更多瞭解,請對我的回答發表評論,我會用更多信息對其進行更新。

更多ARC信息:
Transitioning to ARC Release Notes
LLVM Automatic Reference Counting

+0

你是絕對正確的。如上述評論所述。 ;) – yinkou

+0

我不使用ARC,我嘗試使用與編寫相同的方式播放短音。我只聽到第一個聲音(並且感謝第一次播放聲音時AVAudioPlayer的錯誤)。所以最好你的代碼會削減音頻的第一秒,最壞的情況是它會在聲音自行停止前停止播放。 – Gargo

+0

@Gargo:正如Mattias在他的文章中寫道的那樣,這段代碼解釋了爲什麼玩家沒有在我的案件中工作,這是故意的。如果您沒有經驗,您應該查看AVAudioPlayer教程。 – Phlibbo

3

使用AVAudioPlayer在頭文件伊娃與strong

@property (strong,nonatomic) AVAudioPlayer *audioPlayer 
3

如果需要多個AVAudioPlayers在同一時間播放,創建一個NSMutableDictionary。將該鍵設置爲文件名。從字典通過委託回調,像這樣刪除:

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


    NSString* path = [[NSBundle mainBundle] 
         pathForResource:soundNum ofType:@"m4a"]; 
    NSURL* url = [NSURL fileURLWithPath:path]; 

    NSError *error = nil; 
    AVAudioPlayer *audioPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; 

    audioPlayer.delegate = self; 

    if (_dictPlayers == nil) 
     _dictPlayers = [NSMutableDictionary dictionary]; 
    [_dictPlayers setObject:audioPlayer forKey:[[audioPlayer.url path] lastPathComponent]]; 
    [audioPlayer play]; 

} 

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {   
    [_dictPlayers removeObjectForKey:[[player.url path] lastPathComponent]]; 
} 
+0

這是同時播放聲音的最佳解決方案。如果您使用AVAudioPlayer作爲屬性,則會在播放下一個聲音時發佈對象,而某些用戶正在使用AudioServicesPlaySystemSound,但蘋果拒絕應用程序,因爲它在設備靜音時仍會播放,並且無法檢查設備是否爲靜音。 – Zeeshan