1

Two objects were working just fine receiving NSNotifications before with XCode 5.1 (and CorePlot 1.4). However, with XCode 5.1.1 (Coreplot 1.5) I found that if the addObserver call is inside the init method, it won't actually be registered (just for those two classes, it works in the parent object of a different class). I even put a NSLog before and after the call to make sure the code was still working. The objects are both strongly referenced by their shared parent, and their parent receives the necessary notifications without issue. And, I have a NSLog in the dealloc where the removeObserver is -it is not called early, as the objects are retained properly.

//The object is a CorePlot CPTGraphHostingView
- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        //other code setting up a few private ivar primitive arrays and values

        //this is where the call was (there are actually 3 Observer calls made)
        [[NSNotificationCenter defaultCenter]
        addObserver: self
        selector: @selector(recordUpdated)
        name: @"recordUpdated"
        object: nil];

        //then this is called before the end
        [self prepareGraph];

        //this is where I moved it
        [self startListening];
    }
    return self;
}

Again, nothing has changed about the code for the object sending the notification or those two classes since I last compiled it with XCode 5.1 (and CorePlot 1.4). And this same call is used in the init of the parent, and works perfectly. My only solution last night was to refactor out the addObserver calls into a new method, and call that method at the end of init.

However, I don't understand why this was necessary. Can anyone think of a reason that addObserver placed in the middle of init would be "ignored", but when inside another method called by init, it works?

Edit, and notes:

I added more code to show the init. I also added notes that it is a graph view for CorePlot, and the CorePlot was also recently updated to 1.5 (I forgot about that) -which could be the source of the problem.

lead_the_zeppelin's suggestion that it is being reassigned, seems possible. But wouldn't the call from NSNotificationCenter to a -now- dealloc'd object crash the program (note, dealloc is NOT called - I have a NSLog there)? I could easily test this by printing the object instance string inside the init, and afterwards. I did test this last night, asking for the instance, but I don't think I copied that bit into the init.

Adam Jones
  • 775
  • 6
  • 23
  • 1
    It seems like this must have something to do with the other things happening in your init method. Perhaps posting that would allow us to help? – Jesse Rusak Apr 18 '14 at 13:50
  • Done. Doing so made me realize that I also updated CorePlot recently as well. – Adam Jones Apr 18 '14 at 14:11
  • Just to check, you've got a `NSLog` (or a breakpoint) in the `recordUpdated` method yeah to check its being called? (I know it sounds obvious, but its so easily done!) – Rich Apr 18 '14 at 14:14
  • Also can you post the code which send a notification please :) – Rich Apr 18 '14 at 14:14
  • Are you using ARC? You might try running with NSZombies enabled to see if there's an early dealloc happening. – Jesse Rusak Apr 18 '14 at 14:55
  • @Jesse, Yes, I am using ARC. Dealloc is not being called, as I have a `NSLog` inside the dealloc method, which would warn me - and I can still talk to the object just fine. – Adam Jones Apr 18 '14 at 15:52
  • @Rich, yes there is a NSLog inside the `recordUpdated` method. Actually, it's even more obvious, when it is called the graph on the screen updates. So if it isn't called, nothing happens on the screen. – Adam Jones Apr 18 '14 at 15:52
  • Is it possible that prepareGraph is calling `removeObserver:self`? Maybe something it calls? – Jesse Rusak Apr 18 '14 at 17:04
  • @JesseRusak, `prepareGraph` is a method I wrote. Eric did find the cause in the super class, now I need to find a reliable way around it. – Adam Jones Apr 18 '14 at 20:44

2 Answers2

1

The Core Plot hosting view removes itself as an observer of all notifications whenever you set the hosted graph or the collapsesLayers property. Please post a bug report on the issue tracker if you'd like us to fix it.

In the meantime, add your observers after you set up the graph.

Eric Skroch
  • 27,381
  • 3
  • 29
  • 36
  • I didn't think to wade through the CorePlot source. But, yes, it's there under the `updateNotifications` method. I also noticed that `dealloc` also already calls `removeObserver`. I see there are two methods that call it: `setHostedGraph`, and `setCollapsesLayers`. I think I will post it as a bug, because I wonder how one could reliably subclass `CPTGraphHostingView` without having to regularly re-`addObserver` every time the graph structure is modified. – Adam Jones Apr 18 '14 at 20:20
0

self is probably being reassigned after you subscribe to the notification center. Can you move the code to

-(void)awakeFromNib
{
    [[NSNotificationCenter defaultCenter]addObserver: self  selector:@selector(recordUpdated) name:@"recordUpdated" object:nil];
}

or maybe to -viewDidLoad ?

lead_the_zeppelin
  • 2,017
  • 13
  • 23
  • I added some additional code and a note. These are not UIViews, so they aren't awaken from Nibs. – Adam Jones Apr 18 '14 at 14:10
  • @Adam what does -prepareGraph do? – lead_the_zeppelin Apr 18 '14 at 14:16
  • The Core Plot hosting view is a subclass of UIView. Therefore, your subclass is, too. – Eric Skroch Apr 18 '14 at 15:38
  • @lead_the_zeppelin, prepare graph just does CorePlot things like defining the graph axes and setting up the plot space. – Adam Jones Apr 18 '14 at 15:55
  • 1
    @EricSkroch, You're probably right, but it still doesn't answer -why- it fails in the manner it does. I can already make it work doing something different, and I could move it into `viewDidLoad` (assuming it is called), but it -should- work inside `init`. – Adam Jones Apr 18 '14 at 15:56
  • @Adam Its quite possible prepareGraph is doing something to self. Its always safe to register for notifications outside of init. – lead_the_zeppelin Apr 18 '14 at 15:57
  • @lead_the_zeppelin `prepareGraph` is a method I wrote. Eric did find the cause in the super class, now I need to find a reliable way around it. – Adam Jones Apr 18 '14 at 20:44