12

ile hemen oynamayı durdurur Ben oldukça basit olduğunu düşündüğüm AVAudioPlayer aracılığıyla MP3 çalmaya çalışıyorum. Ne yazık ki, pek işe yaramıyor. İşte tüm yaptım: Test uğrunaAVAudioPlayer, ARC

  • , ben yeni iOS uygulaması Xcode (Tek Görünüm) oluşturuldu.
  • Ben projeye AVFoundation mevzuatının yanı sıra ben Uygulamalar 'Dokümanlar' klasörüne bir MP3 dosyası eklendi ViewController.m

  • için #import <AVFoundation/AVFoundation.h> eklendi.

  • şuna ViewControllersviewDidLoad: değiştirdi:

Kodu:

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

Maalesef ses belli ki çalmaya başlar hemen sonra durur. sleepForTimeInterval'u rahatsız edersem 20 saniye oynar ve sonra durur. Bu sorun, yalnızca ARC ile derlerken oluşur, aksi takdirde, kusursuz çalışır.

+0

Ses yürütmek için başka bir konu başlatmanız gerekmez. Bir şeyin kaydedilip kaydedilmediğini görmek için bir hata işaretçisi sağlamayı denediniz mi? – isaac

+0

hangi hatayı alıyorsunuz? – Daniel

+0

Evet, bir NSError'ı initWithContensOfURL için geçirdim. Yine de sıfır kalır ... Bu yüzden hiçbir hata alamıyorum, sadece hemen oynamaya son veriyor. – Phlibbo

cevap

7

sorun ARC ile derleme yaparken release aramaları ekleyerek size derleyici otomatik olarak "dengesiz" düzeltmek alloc gibi canlı tutmak isteyen örneklerine bir başvuru tutmak için emin olmak gerekir ki (en azından kavramsal olarak, Mikes Ash blog post for more details okumak). Örneği bir özellik veya örnek değişkenine atayarak bunu çözebilirsiniz.

Phlibbo durumda kod dönüştürülecektir:

- (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 
} 

Ve AVAudioPlayer hiçbir referans kaldığında o ayırmanın alır gibi hemen oynamaya duracaktır.

ARC'yi kendim kullanmadım ve kısa bir süreliğine okudum. Bu konuda daha fazla bilgi sahibi olursanız lütfen cevabım hakkında yorum yapın ve daha fazla bilgi ile güncelleyeceğim.

Daha ARC bilgi:
Transitioning to ARC Release Notes
LLVM Automatic Reference Counting

+0

Kesinlikle haklısınız. Yukarıdaki yorumlarda belirtildiği gibi. ;) – yinkou

+0

ARC kullanmıyorum ve yazdığınız gibi kısa sesler çalmaya çalıştım. Sadece ilk sesin sesini duyarım (ve ilk kez bir ses çaldığında AVAudioPlayer ile bir hata verir). En iyi ihtimalle kodunuz bir sesin ilk saniyeleri keser, en kötüsü sesin kendiliğinden durdurulmasından önce çalmayı durdurur. – Gargo

+0

@Gargo: Mattias yazısında yazdığı gibi, kod oyuncunun neden davamda çalışmadığını açıklıyor, kasıtlı olarak hatalı. Bir deneyiminiz yoksa, bir AVAudioPlayer eğitimine bakmalısınız. – Phlibbo

3

Kullanım AVAudioPlayer strong ile başlık dosyasında bir Ivar olarak: Aynı anda oynayan birden AVAudioPlayers gerekiyorsa

@property (strong,nonatomic) AVAudioPlayer *audioPlayer 
3

oluşturmak NSMutableDictionary. Anahtarı dosya adı olarak ayarlayın. Sözlük'ten Delegate Geri Çağırma ile şu şekilde kaldır:

-(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

Bu, aynı anda sesleri çalmak için en iyi çözümdür. AVAudioPlayer özelliğini bir özellik olarak kullanacaksanız, bir sonraki sesi çalacaksanız ve bazı insanlar AudioServicesPlaySystemSound'u kullandıkça yayınlanacak, ancak cihazlar reddedildiğinden ve aygıtın kapalı olup olmadığını kontrol etmek için bir api olmadığı için Apple uygulamaları iptal ediyor. sessiz. – Zeeshan