Using a delegate to pass information from button t

2019-09-10 11:54发布

问题:

I have a Parent View Controller and a Child View Controller, and I need to pass information from a button in the Child View Controller back to the Parent View Controller so that the correct tableViewCell text is highlighted.

In the Parent View Controller when a cell is tapped, the cell text is highlighted, and the Child View Controller pops on screen and plays the song that was selected. However, on the Child View Controller there is a skip backward and skip forward button, so when either of those is pressed and the Parent View Controller is shown again the cell text needs to be highlighted for a different cell now than was highlighted before.

So I've added the proper delegate boilerplate code to each view controller, but I'm not sure the best information to grab from the Child View Controller to send back to the Parent View Controller, and how to use that.

Child View Controller:

-(IBAction)indexChanged:(UISegmentedControl *)sender
{
    NSURL *musicFile = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Blip_Select" ofType:@"wav"]];
    AVAudioPlayer *click  = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile  error:nil];

    switch (self.segmentedControl.selectedSegmentIndex)
    {
        case 0:
            [click play];
            [click play];
            [musicPlayer skipToPreviousItem];
            break;
        case 1:
            [click play];
            if ([musicPlayer playbackState] == MPMusicPlaybackStatePlaying) {
                [musicPlayer pause];
            } else {
                [musicPlayer play];
            }
            break;
        case 2:
            [click play];
            [click play];
            [musicPlayer skipToNextItem];
        default:
            break; 
    } 
}

I would add something inside of each of the above switch statements, but I'm not sure what exactly would work best?

Because this is what it looks like in the Parent View Controller:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    AlbumsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    MPMediaItem *rowItemAlbum = [[albumsArrayForTVC objectAtIndex:indexPath.section] representativeItem];
    NSString *albumDetailTitle = [rowItemAlbum valueForProperty:MPMediaItemPropertyAlbumTitle];
    MPMediaQuery *albumMPMediaQuery = [MPMediaQuery albumsQuery];
    MPMediaPropertyPredicate *albumPredicate = [MPMediaPropertyPredicate predicateWithValue: albumDetailTitle forProperty: MPMediaItemPropertyAlbumTitle];
    [albumMPMediaQuery addFilterPredicate:albumPredicate];
    NSArray *albumTracksArray = [albumMPMediaQuery items];

    MPMediaItem *rowItemSong = [[albumTracksArray objectAtIndex:indexPath.row] representativeItem];
    NSString *songTitle = [rowItemSong valueForProperty:MPMediaItemPropertyTitle];
    cell.textLabel.text = songTitle;
    cell.textLabel.highlightedTextColor = [UIColor brownColor];

    return cell;
}

I know I'd add some sort of method, and reload the table, but I'm not sure the best way to go about this. Any ideas? Thanks!

回答1:

  1. Define a protocol in your child controller. This protocol should have a method like 'didSelectSkipButton' that accepts some parameter to represent the type of button pressed.

  2. Define a delegate property for your child view controller, conforming to the protocol.

  3. In the child's indexChanged, send the didSelectSkipButton message to the delegate, passing the value representing the pressed button.

  4. In your parent vc, set itself up as the child's delegate and implement the protocol methods. In didSelectSkipButton, find the table view's current row using indexPathForSelectedRow and add or subtract one from [indexpath row] depending on the button pressed. Check that the new row index is within the valid bounds for your table view. Then send your table view a selectRowAtIndexPath:animated:scrollPosition: message to select the new row.



回答2:

Create delegate in your child view controller

 @protocol ChildView_Delegate <NSObject>
 -(void)reSelectTableRow:(int)index
 @end

create a property in your child view controller

@property (nonatomic) id delegate;

And when you press forward & backward button do something like this.

-(IBAction)forward:(id)sender{
   if(_delegate){
      [_delegate reSelectTableRow:position+1];
   }
}

Back in your main controller implement ChildView_Delegate & implement it's method like this

 -(void)reSelectTableRow:(int)index{
   if(index<songsArray.count){
     //define a index path
      NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index  inSection:0];
     //select a row of table view programatically
     [tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:
     UITableViewScrollPositionNone];
   }
 }


回答3:

Add delegate method in parent

 @protocol childDelegate <NSObject>
 -(void) updateTable
 @end

and

@property (assign) id <childDelegate> cDelegate;

Then add same method in parent

-(void) updateTable
{
  [yourTableView reloadData];
}

-(IBAction)indexChanged:(UISegmentedControl *)sender
{
  [self.cDelegate updateTable];
}

Hope it helps.