Xcode:无法停止从子类播放 AVAudioPlayer 音乐

Posted

技术标签:

【中文标题】Xcode:无法停止从子类播放 AVAudioPlayer 音乐【英文标题】:Xcode: Unable to stop AVAudioPlayer music playing from sub class 【发布时间】:2014-06-28 13:50:03 【问题描述】:

仍然没有解决方案 - 减少测试用例项目:

http://www.friendlycode.co.uk/assets/Bugfix.zip

我是 Xcode/Objective C 的新手,做了很多研究,但找不到答案。这里有很多类似的问题,但没有一个能帮助我解决这个问题。

文件:

app.h
app.m
Settings.h
Settings.m

我播放了一些背景音乐,当应用程序通过 ViewController.m 文件中的 ViewDidLoad 启动时开始播放。

如果音乐开关被触摸并设置为关闭,我会尝试从 Settings.m 文件中停止此操作。

请参阅下面的代码(已删除不必要的插座/方法等)

NSLog 输出“试图停止音频”,但音频并未停止。我想我已经正确引用了 ViewController 类,所以不确定为什么它不会停止?

app.h

#import <UIKit/UIKit.h>
#import <Social/Social.h>
#import "AVFoundation/AVAudioPlayer.h"

@interface ViewController : GAITrackedViewController <AVAudioPlayerDelegate, UIActionSheetDelegate>

    // removed


@property (nonatomic, retain) AVAudioPlayer *BackgroundMusicPlayer;

@end

app.m

- (void)viewDidLoad

    [super viewDidLoad];

    // Play Background music
    [self PlayBackgroundMusic];


-(void)PlayBackgroundMusic

    NSString* resourcePath = [[NSBundle mainBundle]
                            pathForResource:@"music-file"
                            ofType:@"aiff"];

    NSLog(@"Path to play: %@", resourcePath);
    NSError* err;

    //Initialize our player pointing to the path to our resource
    _BackgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:
              [NSURL fileURLWithPath:resourcePath] error:&err];

    if( err )
        //bail!
        NSLog(@"Failed with reason: %@", [err localizedDescription]);
    
    else
        //set our delegate and begin playback
        _BackgroundMusicPlayer.delegate = self;
        [_BackgroundMusicPlayer play];
        _BackgroundMusicPlayer.numberOfLoops = -1;
        _BackgroundMusicPlayer.currentTime = 0;
        _BackgroundMusicPlayer.volume = 0.5;
    

设置.h

#import <UIKit/UIKit.h>
#import "app.h"

@interface Settings : GAITrackedViewController <AVAudioPlayerDelegate, UIActionSheetDelegate>

    IBOutlet UIButton *BackButton;
    IBOutlet UISwitch *MusicSwitch;
    IBOutlet UISwitch *SoundFXSwitch;


    // Get instance of ViewController object
    ViewController *home;


-(IBAction)BackButton:(id)sender;
-(IBAction)ToggleMusic:(id)sender;
-(IBAction)ToggleSoundFX:(id)sender;


@end

设置.m

#import "Settings.h"

@interface Settings ()

@end

@implementation Settings

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.



- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


-(IBAction)ToggleMusic:(id)sender 

    // Get instance of ViewController object

    //home = [[ViewController alloc] init];

    if (MusicSwitch.on)
    
        [home.BackgroundMusicPlayer play];
    
    else 
       [home.BackgroundMusicPlayer stop];
        NSLog(@"Attempting to stop audio");

    


-(IBAction)ToggleSoundFX:(id)sender 

    if (SoundFXSwitch.on)
    
    
    else

    


-(IBAction)BackButton:(id)sender

    [self dismissViewControllerAnimated:YES completion:nil];

【问题讨论】:

如果有人想测试他们的答案,我已经创建了一个简化的测试用例项目:friendlycode.co.uk/assets/Bugfix.zip 我已经通过在 AppDelegate 中声明 AVAudioPlayer 来修复它。 我无法让你的方法工作 - 请编辑简化的测试用例并上传到某个地方。如果它有效,我会奖励你最好的答案 【参考方案1】:

我认为问题出在 ViewController *home 上。

您的 AvAudioPlayer 对象位于界面 ViewController 的 app.h 中。

但是在您的代码中,您没有初始化 ViewController 对象“home” 在设置.m。如此有效,你正试图访问并阻止一个玩家 未创建。

要访问 AVAudioPlayer 对象,请在 settings.h 的 viewDidload 中添加以下代码。

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //initialise the audioPlayer object.
    home=[[ViewController alloc] init];

【讨论】:

感谢您的回复。嗯,也没有用:( 请你看看简化的测试用例?:friendlycode.co.uk/assets/Bugfix.zip 这就是问题所在。如果没有正确实例化“home”,您将无法访问“home”的 backgroundMusicPlayer 属性。试试:self.home = [[ViewController alloc] init]; 或者_home【参考方案2】:

在您的 Settings.h 中,将 ViewController 属性声明为 assign

@interface Settings : GAITrackedViewController <UIActionSheetDelegate>

    @property (nonatomic, assign) ViewController *home;



-(IBAction)ToggleMusic:(id)sender 

    if (MusicSwitch.on)
    
        [self.home.BackgroundMusicPlayer play];
    
    else 

       [self.home.BackgroundMusicPlayer stop];
    

从您的 app.m 中,将 home 属性分配为 self _BackgroundMusicPlayer.home = self;

-(void)PlayBackgroundMusic

    NSString* resourcePath = [[NSBundle mainBundle]
                            pathForResource:@"music-file"
                            ofType:@"aiff"];

    NSLog(@"Path to play: %@", resourcePath);
    NSError* err;

    //Initialize our player pointing to the path to our resource
    _BackgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:
              [NSURL fileURLWithPath:resourcePath] error:&err];

    if( err )
        //bail!
        NSLog(@"Failed with reason: %@", [err localizedDescription]);
    
    else
        //set our delegate and begin playback
        _BackgroundMusicPlayer.delegate = self;
        settingsViewObj.home = self; //recommended after the 'Settings' view allocation code.
        [_BackgroundMusicPlayer play];
        _BackgroundMusicPlayer.numberOfLoops = -1;
        _BackgroundMusicPlayer.currentTime = 0;
        _BackgroundMusicPlayer.volume = 0.5;
    

注意事项:

阅读有关对象通信的更多信息

阅读有关 Objective C 编码标准的更多信息

阅读有关类层次结构的更多信息

【讨论】:

感谢您的回答和说明 - 我一定会阅读更多内容!当我在行中添加 *_BackgroundMusicPlayer.home = self; 时,我收到错误 Property 'home' not found on type of 'AVAudioPlayer '。如何将“home”添加为 AvAudioPlayer 的对象? 哦,真的很抱歉。我已经编辑了答案。写 settingsViewObj.home = self;在“设置”视图分配代码之后。 获取“使用未声明的标识符 settingsViewObj”。我需要声明吗?它没有在其他地方使用? 您如何访问“设置”类? @FriendlyCode:我已经回复了。请检查。【参考方案3】:

如果我正确理解了您的代码,您似乎正在创建初始视图控制器的实例并试图停止该实例的音乐播放器属性。如果是这种情况,您尝试停止的音乐播放器已经停止,因为它是一个单独的 AVAudioPlayer 实例,它是在您创建 ViewController 实例时创建的。为了从第一个视图控制器停止音乐播放器,你可以试试这个:

    在 Settings.h 文件中,添加一个 AVAudioPlayer 属性,就像在 app.h 中一样

    @property (strong, nonatomic) AVAudioPlayer *backgroundMusic;
    

    然后当 segue 到设置视图控制器时,使用 prepareForSegue 将音频播放器传递给新控制器:

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    
        if([segue.identifier isEqualToString:@"YourSegueName"]) 
            if([segue.destinationViewController isKindOfClass:[YourSettingsClass class]]) 
                YourSettingsClass *destination = segue.destinationViewController;
                destination.backgroundMusic = self.BackgroundMusicPlayer;
            
        
    
    

    您现在应该可以简单地拨打[self.backgroundMusic stop] 并停止您的音乐。

确保您在应用程序类中#import 设置控制器类以在 prepareForSegue 方法中访问它。

【讨论】:

感谢您的详细解答。我已经尝试过了,但我仍然无法让它工作。我给 Segue 起了一个名字,并把它和你提供的代码联系起来,看起来它应该可以工作,但就是不行 :-( 请你看看简化的测试用例?:friendlycode.co.uk/assets/Bugfix.zip 我刚刚使用我上面描述的方法让它工作。确保您在故事板中为您的 segue 提供了一个标识符,并且您的开关已正确连接到您的设置类作为 IBOutlet。【参考方案4】:

您不能通过导入来访问由它创建的另一个类的对象的实例 it.Here 你必须访问同一个对象实例,才能停止 AVAudioPlayer。

因此,您必须将对象放置在唯一的位置,例如 AppDelegate。

尝试在 appdelegate.h 中声明 AVAudioPlayer。

在 Appdeleagte.h 中

@property (nonatomic, strong) AVAudioPlayer *BackgroundMusicPlayer;

在您的 app.h 中,您可以按如下方式访问播放器。

AppDelegate *appDelegate;

//in your viewDidLoad
    appDelegate=[[UIApplication sharedApplication]delegate]; 

//in your PlayBackGroundMusic
       appdelegate.avAudioPlayer=[[AVAudioPlayer alloc] initWithContentsOfURL:
                  [NSURL fileURLWithPath:resourcePath] error:&err];
       [appDelegate.avAudioplayer play];

在您的设置中。h

AppDeleagte *appDelegate;

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    //initialise the audioPlayer object.
    appDelegate=[[UIApplication sharedApplication]delegate]; 



你可以通过

停止播放器
[appDelegate.avAudioPlayer stop];

可以下载固定工程@9​​87654321@

【讨论】:

你好,你可以在这里下载固定文件mydeveloperzone.in/wp-content/uploads/Bugfix%202.zip

以上是关于Xcode:无法停止从子类播放 AVAudioPlayer 音乐的主要内容,如果未能解决你的问题,请参考以下文章

从 Xcode 启动 iOS 模拟器并得到黑屏,然后 Xcode 挂起并且无法停止任务

XCode4 无法正确生成 NSManagedObject 子类

仅当我单击全屏选项卡时才以纵向播放视频,它会停止播放(Xcode 4.6)ios6.1

在 xcode 中的断点处停止时,Mac 音频停止

无法从其他线程播放 QMediaPlayer

xcode sprite kit 背景音乐