I'm about to build this app where users can listen to tracks populated in a uiTableView. When the user hits a row, it should notify the other class (my audio player) about this action and ect. load the mp3 url.

Illustration of my storyboard architecture, the top line illustrates the two view controllers that needs to communiate

The reason why I choose to have a view controller in front of the navigation controller is simply. I need a persistent view (my audio player, marked with dark grey) to be displayed on every view controllers, and I found this solution the easiest. My issue here is how to tell the audio player class about actions happening in trackTableView. I know you can use delegation, but don't know how it's done in a proper way when there's a navigationController in between.

Another thing I have thought about is the use of having the audio player as a singleton (It will be like this anyway, as I only need one instance of the audio player) and then just call the singleton method's when I need it.

What is the best way to handle it, singleton methods or delegation? And how is the delegation done in a situation like this?

有帮助吗?

解决方案

Usually delegation is a good pattern for this, since it is the 'cleanest' way. The interfaces are all design etc.

The problem in this case will be, that when you initiate the tableview's delegate you need to set the (your) audioplayer delegate. Therefore you would need a reference to the audioplayer somewhere else in your code. For this reason I would suggest using a singleton.

The last pattern I would like to talk about would be using Notifications (NSNotificationCenter + NSNotification). Usually you don't just want to control your audio player when the user selects a new title etc. but also have other things happening like updating the playlist, update view that display what's going on etc.

If these things are all in different portions of your code ( and not directly controlled by your audio player) then notifications would also be really handy!

For best practice I would suggest: Control all your code for displaying and managing playlist from a central singleton. If this is not what you did then use notifications!

If you don't know how NSNotificationCenter works, here is a short code sample:

[[NSNotificationCenter defaultCenter] postNotificationName:@"START_MUSIC" object:nil userInfo:nil];

This will post a notification to all the listeners waiting for a notification called @"START_MUSIC". If you need to provide extra data, for instance which song was selected etc. you can create an NSDictionary and add it to the userInfo-parameter (I left it nil in this case)

Then in another class where you want to receive this notification you call

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startMusic:) name:@"START_MUSIC" object:nil];

And you have to implement

- (void)startMusic:(NSNotification *)notification
{
    // if you provided some extra information, this is where you get your dictionary!
    NSDictionary* userInfo = notification.userInfo;
}

You should also stop listening for notifications when this object is being deallocated! Therefore add this to your -(void)dealloc method:

- (void)dealloc
{
     // rest of your dealloc code!
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    // if not using ARC:
    // [super dealloc]
}

In general if you want to stop listening for notifications you can use the -(void)removeObserver:(id)observer method of the notification center or the other more detailed once (for instance stop listening for a specific notification). If you just call this general method you stop listening for all notifications with this object.

其他提示

you can handle the playing use a shared instance (just call it sharedPlayer), treat the PlayingViewController as a normal instance VC. when user tap the tableview cell to select a track, alloc and push the PlayingViewController with the selectedTrack. then call the sharedPlayer in the view controller.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top