Question

The problem is that I have three NSNotificationcenter's setup to listen for user changing songs, volume and playlists. The app works correctly with playing songs from users selections from a playlist.

When the user selects the song to play, it usually registers the users action to play the song and changes the playbackState but sometimes it fails to do so. Creating a continual loop of only allowing play and play and not stop. (Basically there is an intermittent fault with the code.)

The problem I believe is that NSNotificationcenter call from one action is overwritten by another NSNotificationcenter call out. Cancelling one call out over another. Thus rendering the user unable to stop playing the song.

App function: Allow user to select playlist from PickerView, load songs from playlist and allow user to select songs from TableView to play.

- (void)addMusicPlayerObserver {

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleNowPlayingSongStateChanged:)
                                                 name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
                                               object:self.musicPlayer];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handlePlaybackStateChanged:)
                                                 name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                                               object:self.musicPlayer];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleVolumeChangedFromOutSideApp:)
                                                 name:MPMusicPlayerControllerVolumeDidChangeNotification
                                               object:self.musicPlayer];
    [self.musicPlayer beginGeneratingPlaybackNotifications];
}

- (void)removeMusicPlayerObserver {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
                                                  object:self.musicPlayer];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMusicPlayerControllerPlaybackStateDidChangeNotification
                                                  object:self.musicPlayer];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:MPMusicPlayerControllerVolumeDidChangeNotification
                                                  object:self.musicPlayer];
    [self.musicPlayer endGeneratingPlaybackNotifications];
}

Full code for the implentation+header

http://pastebin.com/vL12zFrQ

Any help would be great.

Was it helpful?

Solution

You have two handler : One for notifications, one for your button action (it seems you created a play/pause button in your app).

You shoud remove this line from your button handler since your notification handler do the same work.

[self._playPauseButton setTitle:@"Play" forState:UIControlStateNormal];

I also advise to do

if (playbackState == MPMusicPlaybackStatePlaying) {
    [self.musicPlayer pause];
}
else {
    [self.musicPlayer play];
}

to be sure there won't be any state you don't handle that block your way. (And same idea to your notification handler)

Also, the advice of @rckoenes is good, try to handle every Notification, not only the one of your object.

Also try to remove the self.musicPlayer in the object parameter of the NSNotificationCenter and check if it works then.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top