views:

19

answers:

1

I have a root view and a detail view, in the detail view is a AVAudioPlayer with a basic play/pause button setup. All works, however if I play the file and then click back (popViewControllerAnimated) to the root, the file keeps playing which is correct, but then if I click back to the detail view the view has reset and doesn't find the instance of the AVAudioPlayer.

Detail page.h

@interface DetailPageViewController : UIViewController <AVAudioPlayerDelegate>{
UIButton *arrowBtn;
UIButton *playButton;
UIButton *pauseButton;
AVAudioPlayer *appSoundPlayer;
NSURL *soundFileURL;
BOOL playing ;
UILabel *timeLabel;
NSTimer *timer;
}

@property (nonatomic, retain) IBOutlet UIButton *arrowBtn;
@property (nonatomic, retain) IBOutlet UIButton *playButton;
@property (nonatomic, retain) IBOutlet UIButton *pauseButton;
@property (nonatomic, retain)   AVAudioPlayer *appSoundPlayer;
@property (nonatomic, retain)   NSURL *soundFileURL;
@property (nonatomic, retain)   IBOutlet UILabel *timeLabel;
@property (readwrite) BOOL playing;
@property (nonatomic, retain) NSTimer *timer;

-(IBAction)playPauseToggle:(id)sender;
-(IBAction)returnToRoot;

@end

Detail page.m

@synthesize arrowBtn, playButton, pauseButton, playing, appSoundPlayer, soundFileURL, timeLabel, timer;

...

-(IBAction)playPauseToggle:(id)sender
{
if (playing == NO)
{
    [appSoundPlayer play];
    playing = YES;
    [playButton setHidden: YES];
    [pauseButton setHidden: NO];

}
else {
    [appSoundPlayer pause];
    playing = NO;
    [playButton setHidden: NO];
    [pauseButton setHidden: YES];
}
}

-(IBAction)returnToRoot
{
[self.navigationController popViewControllerAnimated:YES];
}

- (void)viewDidLoad {
[super viewDidLoad];

if (self.appSoundPlayer == nil)
{
    playing = NO;

    [playButton setHidden: NO];
    [pauseButton setHidden: YES];

    NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"soundFile" ofType:@"mp3"];

    NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
    self.soundFileURL = newURL;
    [newURL release];

    AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
    self.appSoundPlayer = newPlayer;
    [newPlayer release];

    [appSoundPlayer prepareToPlay];
    [appSoundPlayer setVolume: 1.0];
    [appSoundPlayer setDelegate: self];
}

}

How do I persist either appSoundPlayer or playing when I view the view again.

+1  A: 

You would need to keep a reference to the appSoundPlayer object on your RootViewController, and pass it in some way to your detail view when loading it.

Actually the BOOL playing is not necessary, because it is a property of AVAudioPlayer and you can access this whenever you want.

RootViewController.h

@interface RootViewController : UIViewController {
    AVAudioPlayer *_appSoundPlayer;

// Declare the other iVars
}

@property (nonatomic, retain) AVAudioPlayer *appSoundPlayer;

@end

RootViewController.m

@synthesize appSoundPlayer = _appSoundPlayer;

- (void)dealloc {
    [self setAppSoundPlayer:nil];
    // Dealloc the other properties that you may have

    [super dealloc];
}
/*
** Your code
*/

// When presenting the detail view
- (void)openDetailView {
    DetailPageViewController *viewController = [[DetailPageViewController alloc] initWithParentViewController:self];
.
.
.
    // Present the view controller
}

On your DetailPageViewController.h

@interface DetailPageViewController : UIViewController <AVAudioPlayerDelegate> {
RootViewController *_parentViewController;
    // Declare the iVars
}

@property (nonatomic, assign) RootViewController *parentViewController;

- (id)initWithParentViewController:(RootViewController *)parentViewController;

@end

DetailPageViewController.m

@synthesize parentViewController = _parentViewController;

- (void)dealloc {
    // Set the delegate to nil
    [self.parentViewController.appSoundPlayer setDelegate:nil];

    // Dealloc the other properties that you may have

    [super dealloc];
}

- (id)initWithParentViewController:(RootViewController *)parentViewController {
    if (self = [super init]) {
        self.parentViewController = parentViewController;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    if (self.parentViewController.appSoundPlayer == nil) {
        [playButton setHidden: NO];
        [pauseButton setHidden: YES];

        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"soundFile" ofType:@"mp3"];

        NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
        self.soundFileURL = newURL;
        [newURL release];

        AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
        [newPlayer prepareToPlay];
        [newPlayer setVolume: 1.0];
        [newPlayer setDelegate: self];
        self.parentViewController.appSoundPlayer = newPlayer;
        [newPlayer release];
    }
}

I haven't tested this code but you can have a good idea of what you will need to do. Of course, there are other ways to do this.

vfn
thank you for the answer. I'm starting to get it, but get the following errors:`duplicate member '_parentViewController'', `warning: no -initWithParentViewController:initWithNibName:bundle:' method found`` ?
daidai
@daidai, you are get a warning because the method that you are looking for doesn't exist, you have to create the method -initWithParentViewController:initWithNibName:bundle:, based on the one that I've created -initWithParentViewController:
vfn
thanks, fixed. however its still complaining about `duplicate member '_parentViewController'`, but I change (in DetailPageViewController.h) `RootViewController *_parentViewController;` to `RootViewController *parentViewController;` it compiles, but crashes (with warnings of local declaration of 'parentViewController' hides instance variable and property 'parentViewController' type does not match super class 'UIViewController' property type. thanks for your help, im slowly understanding the principles.
daidai