7

In my UITableViewCell I have a method initNotification which is called by the TableViewController in cellForRowAtIndexPath where the TableCells are created.

My Problem is that, every time this view is reloaded, the initNotification method is called again, so when the Notification appears, the NotificationHandle is called x-times!

I have tried to remove the Observer before adding it again with:

-(void) initNotification{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(handleNotificationOnOff:)
     name:[[NSString alloc] initWithFormat:@"%@",[self.light beckhoffOnOff]]
     object:nil];
}

but this do not work either. The Problem is, I cannot use a bool-flag or anything like that, because the Cells are always reinitialized by the ViewController.

Is there a proper way to remove the NotificationHandle form the NotificationCenter?

edit: This is how I create my custom TableViewCells

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    Light* l = [[staticModel.model getRoomAtIndex:[indexPath section]]getLightAtIndex:[indexPath item]];
    if([l typ]==ONOFF){
        TableCellLight *conof = [tableView dequeueReusableCellWithIdentifier:@"ReuseIDOnOff" forIndexPath:indexPath];
        LightOnOff *lonof = (LightOnOff*) l;
        [[conof label] setText: [lonof bezeichnung]];
        conof.light=lonof;

        [conof initNotification];
        cell = conof;
    }
   if([l typ]==DIMMER){
        TableCellLightDim *cdim = [tableView dequeueReusableCellWithIdentifier:@"ReuseIDDim" forIndexPath:indexPath];

        LightDim *ldim= (LightDim*) l;
        [[cdim label] setText: [ldim bezeichnung]];
        [[cdim slider]setValue:[ldim dimVal]];
        cdim.light=ldim;
        [cdim initNotification];
        cell = cdim;
    }
    if([l typ]==RGB){
        TableCellLightRGB *crgb = [tableView dequeueReusableCellWithIdentifier:@"ReuseIDRGB" forIndexPath:indexPath];
        LightRGB *lrgb= (LightRGB*) l;
        [[crgb label] setText: [lrgb bezeichnung]];
        crgb.light=lrgb;
        crgb.owner=self;
        [crgb initNotification];
        cell = crgb;
    }

    return cell;
}

Thanks

user2071938
  • 2,055
  • 6
  • 28
  • 60

1 Answers1

13

Generally speaking the cell shouldn't be observing anything. The controller should be observing changes and pushing the updated information onto the cells.

Calling removeObserver: before adding the observer should work. If you were going to do anything in prepareForReuse or tableView:didEndDisplayingCell:forRowAtIndexPath: to reset the cell, that would be the code you use. You need to look at how you tested that it wasn't working and how you're reusing cells.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • Thanks for the reply! I have figured out why removeObserver: doesn't work, because self is not the same anymore, every time the TableView is reloaded(and the cells as well) I get a new instance of every cell. Is there a way to force the cells to deallocate ? – user2071938 Jul 12 '13 at 07:29
  • If you don't reuse the cells they should be released (as in, you don't have a reuse identifier). But that isn't ideal. – Wain Jul 12 '13 at 07:38
  • I have an reuse identifier but why ends that to so many instances of the same cell? – user2071938 Jul 12 '13 at 07:41
  • You'd have to show the code. How are you counting the number of cell instances? The count should be just over the number of cells on screen if you're doing it correctly. – Wain Jul 12 '13 at 07:44
  • Every cell has it's own notification, in the notification handle I have a NSLog(self) so I could count how often the handle is called(should only called once!) - I have added the code where I create the cells to my question. – user2071938 Jul 12 '13 at 07:48
  • 1
    Try using `tableView:didEndDisplayingCell:forRowAtIndexPath:` to tell each cell to remove itself as an observer when it is removed from the screen. – Wain Jul 12 '13 at 08:36
  • @Wain would your recommend this for KVO as well? – kernix Jul 27 '15 at 19:37
  • What if a cell contains a collection (or table) view, who is supposed to observe notifications? :-P – Jonny May 22 '17 at 08:47
  • @Jonny consider using a child view controller – Wain May 22 '17 at 08:51
  • 1
    @Wain I'm using a VC with a table view, where some of the cells contain a collection view, those cells contain things that relate to models that need observing. Observing the model from the last point in the view class makes perfect sense to me, after all they know best what kind of data they care about. Nonetheless this time I actually went with observing only in the VC for now - the VCs refresh visible cells only. I believe iOS cells are pretty tricky after all. – Jonny May 22 '17 at 09:53
  • @Jonny my cell is containing an Avplayer, for which i need to observe KVO to detect when the video has finished downloading.in that case what would you recommend? – elk_cloner Aug 22 '20 at 23:49