菜鸟教程小白 发表于 2022-12-12 16:39:51

ios - AVAudioPlayer 始终为 nill,其 isPlaying 属性始终为 false。播放时文件混合


                                            <p><p>过去三天我一直在拔头发来解决这个问题。我检查了很多示例代码,阅读了很多教程,并在 stackoverflow 上搜索并检查了很多很多问题和答案,但我仍然无法解决问题。有几个类似的问题,如 <a href="https://stackoverflow.com/questions/3119731/avaudioplayer-isplaying-always-return-null" rel="noreferrer noopener nofollow">this</a>或 <a href="https://stackoverflow.com/questions/17807987/multiple-songs-playing-simultaneously-using-avaudioplayer-in-ios" rel="noreferrer noopener nofollow">this</a>但他们也没有任何解决方案。</p>

<p>关于我的项目的一点点:</p>

<p>我有一个 <code>NIKMasterViewController</code> 和一个 <code>NIKDetailViewController</code>。在第一个中,我在表格 View 中有一个音频文件列表;选择一行,它导航到 <code>NIKDetailViewController</code>,用户可以在其中查看有关文件的一些信息并播放音频文件。
我在 <code>NIKMasterViewController</code> 中定义了一个 <code>AVAudioPlayer</code> 属性并将其设置为:
<code>NIKMasterViewController.h</code>:</p>

<p><code>@property (nonatomic, strong) AVAudioPlayer *audioPlayer;</code></p>

<p><code>NIKMasterViewController.m</code>:</p>

<pre><code>@synthesize audioPlayer;

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([ isEqualToString:@&#34;showDetail&#34;])
    {
      NSIndexPath *indexPath = ;
      NIKDetailViewController *detailViewController = (NIKDetailViewController *) segue.destinationViewController;
      ;

       feedItems] objectAtIndex:indexPath.row]];

    } else {
      NSLog(@&#34;Segue Identifier: %@&#34;, segue.identifier);
    }

}
</code></pre>

<p>这就是 <code>NIKMasterViewController</code> 中的 <code>AVAudioPlayer</code> 的全部内容。现在在我的 <code>NIKDetailViewController</code> 我有 <code>AVAudioPlayer</code> 的另一个属性:</p>

<p><code>NIKDetailViewController.h</code>:</p>

<p><code>@property (nonatomic, strong) AVAudioPlayer *audioPlayer;</code></p>

<p>现在在我的 .m 文件中,我有一个名为 <code>streamAudio</code> 的方法,该方法在 <code>viewDidLoad</code> 中调用以准备音频播放,并且我有一个 <code>if</code> 条件要求检查 <code>audioPlayer</code> 是否为 <code>nill</code>,如果不是,则 <code>audioPlayer.isPlaying</code> 是否为真,以便 <code>stop </code> 是播放器,但它从未被调用,当我导航回 Master VC 以点击另一行播放另一个文件时,第二个文件开始播放,而第一个文件正在播放,一切都搞混了。 </p>

<p>任何帮助都将不胜感激,因为在数小时和数天后无法解决此问题后,我几乎要停止编程了!</p>

<p><code>NIKDetailViewController.m</code>:</p>

<pre><code>@synthesize audioPlayer;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = ;
    if (self) {
      // Custom initialization
      selectedItem = [init];
    }
    return self;
}


#pragma mark - Managing the Audio Playback


- (IBAction)togglePlayingState:(id)button
{
    //Handle the button pressing
    ;
}



- (void)playAudio
{
    //Play the audio and set the button to represent the audio is playing
    ;
    forState:UIControlStateNormal];
}

- (void)pauseAudio
{
    //Pause the audio and set the button to represent the audio is paused
    ;
    forState:UIControlStateNormal];

}

- (void)togglePlayPause
{
    //Toggle if the music is playing or paused
    if (!audioPlayer.playing)
    {
      ;
    }
    else if (audioPlayer.playing)
    {
      ;
    }
}


- (void)streamAudio
{   
    currentFileName = [ lastPathComponent];

    NSString* documentPath = ;
    NSString* path = ;
    NSURL* audioURL = ;

    if (audioPlayer != nil)
    {
      if (audioPlayer.isPlaying)
      {
            ;//THIS IS NEVER CALLED
      }
      audioPlayer = nil;         //THIS IS NEVER CALLED
    }

    audioPlayer = [ initWithContentsOfURL:audioURL error:nil];

    // Set a timer which keep getting the current music time and update the UISlider in 1 sec interval
    playbackTimer = ;
    // Set the maximum value of the UISlider
    seekSlider.maximumValue = audioPlayer.duration;


    currentTime.text = ;
    remainingTime.text = ;

    // Set the valueChanged target
    ;
    audioPlayer.delegate = self;
    ; //Add the audio to the memory.
}


- (void)updateSlider
{
    // Update the slider about the music time
    seekSlider.value = audioPlayer.currentTime;
}

- (IBAction)sliderChanged:(UISlider *)sender {
    // Fast skip the music when user scrolls the slider
    ;
    ;
    audioPlayer.delegate = self;

    ;
    ;
}

// Stop the timer when the music is finished (Need to implement the AVAudioPlayerDelegate in the Controller header)
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    // Music completed
    if (flag) {
      ;
    }
}


- (IBAction)forwardAudio:(id)sender
{
    int currentTime = ;
    ;
}

- (IBAction)rewindAudio:(id)sender
{
    int currentTime = ;
    ;
}


//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    //if it is a remote control event handle it correctly
    if (event.type == UIEventTypeRemoteControl) {
      if (event.subtype == UIEventSubtypeRemoteControlPlay) {
            ;
      } else if (event.subtype == UIEventSubtypeRemoteControlPause) {
            ;
      } else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
            ;
      }
    }
}

#pragma mark - view life cycle


- (void)viewDidAppear:(BOOL)animated {
    ;

    //Once the view has loaded then we can register to begin recieving controls and we can become the first responder
    [ beginReceivingRemoteControlEvents];
    ;
}

- (void)viewWillDisappear:(BOOL)animated {
    ;

    //End recieving events
    [ endReceivingRemoteControlEvents];
    ;
}

- (void)viewDidLoad
{
    ;
    // Do any additional setup after loading the view, typically from a nib.

    ;

    //Make sure the system follows our playback status - to support the playback when the app enters the background mode.
    [ setCategory:AVAudioSessionCategoryPlayback error:nil];
    [ setActive: YES error: nil];

}

- (void)didReceiveMemoryWarning
{
    ;
    // Dispose of any resources that can be recreated.
}
@end
</code></pre>

<p><strong>注意:</strong>我已尝试将 Detail VC 中的属性设置为 <code>weak</code> 但随后我收到警告,并且在播放文件之前该属性已释放.</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>所以...我终于可以通过创建 <code>audioplayer</code> 的 <code>singleton</code> 来解决这个问题。方法如下:</p>

<ol>
<li>首先,我从我的 <code>NIKMasterViewController</code> 类中删除了所有与 <code>audioPlayer</code> 相关的代码,其中包括 <code>audioPlayer</code> 声明并设置它在 <code>prepareForSegue</code> 中。 </li>
<li>我创建了一个名为 <code>NIKAudioPlayer</code> 的新类。</li>
<li><p>在 <code>NIKAudioPlayer.h</code>:</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;
#import &lt;AVFoundation/AVFoundation.h&gt;

@interface NIKAudioPlayer : NSObject &lt;AVAudioPlayerDelegate&gt;
{
    AVAudioPlayer *currentPlayer;
}
@property (nonatomic, strong) AVAudioPlayer *currentPlayer;
+(NIKAudioPlayer *) sharedPlayer;
-(void)playURL:(NSURL*)url;
@end
</code></pre> </li>
<li><p>在 <code>NIKAudioPlayer.m</code>:</p>

<pre><code>#import &#34;NIKAudioPlayer.h&#34;

@implementation NIKAudioPlayer
@synthesize currentPlayer;

+(NIKAudioPlayer *) sharedPlayer
{
    static NIKAudioPlayer* sharedPlayer;
    static dispatch_once_t onceToken;
    dispatch_once(&amp;onceToken, ^{
    sharedPlayer = [ init];
    });
    return sharedPlayer;
}

-(void)playURL:(NSURL*)url
{
    ;
    currentPlayer = [ initWithContentsOfURL:url error:nil];
    ;
}

@end
</code></pre> </li>
<li><p>现在在代码中的其他任何地方(在我的例子中是 <code>NIKDetailViewController</code>),每当我需要播放音频文件时,我都会从 <code> 调用 <code>sharedPlayer</code> >NIKAudioPlayer</code>:</p>

<pre><code>[ playURL:audioURL];
[.currentPlayer prepareToPlay];
</code></pre> </li>
</ol>

<p>简而言之,将 <code>NIKDetailViewController</code> 中的所有 <code>audioPlayer</code> 替换为 <code>.currentPlayer</code>,甚至将其转换并使用它无处不在:</p>

<p><code>audioPlayer = .currentPlayer</code></p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - AVAudioPlayer 始终为 nill,其 isPlaying 属性始终为 false。播放时文件混合,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/20164873/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/20164873/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - AVAudioPlayer 始终为 nill,其 isPlaying 属性始终为 false。播放时文件混合