Question

I have a table view where each cell can play a message, similar to the voicemail table view from the iphone with the difference that the slider and progress labels are part of the cell: Apple's Voicemail audio cells
(source: apcmag.com)

The table is associated with CoreData where each managed object contains a link to the audio files for the table view cells.

Since the play button, slider, and audio time progress labels are part of each cell, each AudioCell (which is the custom cell that inherits from UITableViewCell) contains an AVAudioPlayer object to respond to the user actions (e.g. play, pause, etc...).

When I start playing the audio from a cell, I need to save that cell in a memvar so the AVAudioPlayer object inside the cell can keep playing the audio and the labels and slider are updated correctly. Here is the code where I "save" the audio playing cell to the memvar: #pragma mark - AudioCellDelegate

- (void)playbackChangedForAudioCell:(AudioCell *)audioCell
{
    if (self.audioPlayingCell.isPlaying && ![self.audioPlayingCell isEqual:audioCell]) {
        [self.audioPlayingCell stopPlayback];
    }

    if (audioCell.isPlaying) {
        self.audioPlayingCell = audioCell;
    } else{
        self.audioPlayingCell = nil;
    }

    // Mark the message as played.
    Message *message = (Message *)[[self fetchedResultsControllerForTableView:self.tableView] objectAtIndexPath:audioCell.cellIndexPath];

    [self messageSeenByUser:message];
}

Here is the relevant code where the cell is "restored" from the memvar if it matches the NSIndexPath that is currently playing audio:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObject *managedObject = [[self fetchedResultsControllerForTableView:tableView] objectAtIndexPath:indexPath];

    UITableViewCell *cell = nil;

    // Implement any new kind of message here.
    if ([managedObject isKindOfClass:[VoicemailMessage class]])
    {
        if ([self.audioPlayingCell.cellIndexPath isEqual:indexPath])
            cell = self.audioPlayingCell;
        else {
            AudioCell *audioCell = (AudioCell *)[self setupCellForVoicemail:(VoicemailMessage*)managedObject];
            audioCell.cellIndexPath = indexPath;
            cell = audioCell;
        }
    } 

The problem is that when the NSManagedObject is updated at:

- (void)messageSeenByUser:(Message *)message
{
    if (self.view.window) {
        if ([message.isNew boolValue])
        {
            message.isNew = [NSNumber numberWithBool:NO];
            [[NSNotificationCenter defaultCenter] postNotificationName:MessageBadgeNotification object:self];
        }
    }
}

the cell disappears from the table view (the space is still there, but I can't see any widget from the cell).

BUT, if there are no changes to the NSManagedObject and the table reloads the cell does not disappear.

I would like to know what could be causing the cell to disappear, something must be different from the regular table view update and the managed object change.

Was it helpful?

Solution

I got it working, the problem seems to be the fade animation that is added when the cell needs to be updated with the Managed Object change at:

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{   
    UITableView *tableView = self.tableView;

    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            self.insertedRow = YES;
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
                    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];// Do not add an animation or the voicemail cell will 

At NSFetchedResultsChangeUpdate, instead of make it use the fade animation, I am not adding any animation and that seems to have solved the cell disappearing problem.

I am still not sure what could be causing the cell to disappear with the fade animation but at least it does not disappear now after this change. If anyone knows why it disappears with the fade animation, it is welcome to comment.

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