4

I'm using a SplitViewController. In MasterViewController's viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadMasterTable:) name:ReloadMasterTableNotification object:_detailViewController];

In DetailViewController, I have two text fields. On didEndEditing:

- (void)textFieldDidEndEditing:(UITextField *)textField {
    if ([_detailItem isKindOfClass:[Pill class]]) {
        Pill *p = (Pill *)_detailItem;

        if (textField.tag == TEXTFIELD_NAME_TAG) {
            p.name = textField.text;
        }

        if (textField.tag == TEXTFIELD_NOTE_TAG) {
            p.note = textField.text;
        }

        [self updateMasterTableView];
    }
}


- (void)updateMasterTableView {
    if ([_detailItem isKindOfClass:[Pill class]]) {
        Pill *currentPill = (Pill *)_detailItem;

        NSUInteger indexToReplace = [[[DataManager sharedInstance] pillArray] indexOfObject:currentPill];
        [[[DataManager sharedInstance] pillArray] replaceObjectAtIndex:indexToReplace withObject:currentPill];

        NSLog(@"i should update row: %i", indexToReplace);

        NSIndexPath *path = [NSIndexPath indexPathForRow:indexToReplace inSection:0];
        NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:path, @"IndexPath", nil];
        [[NSNotificationCenter defaultCenter] postNotificationName:ReloadMasterTableNotification object:self userInfo:dict];
    }
}

From the NSLog, when the text field delegate method gets called, it only gets called once, and then updateMasterTableView gets called once. When I run it through the debugger, putting a break point on the reloadMasterTableView: method, it goes through the method twice. Why is that? Thanks.

Or if there is a better way to synchronize between the two views, I'm all ears.

Crystal
  • 28,460
  • 62
  • 219
  • 393
  • How are you registering for notifications? It could be that you're registering for the same notification twice.. – Snowman May 16 '12 at 02:30
  • Have you confirmed with logging that reloadMasterTable is actually being called twice, or just with breakpoints? – Joel May 16 '12 at 02:33
  • The breakpoint is on reloadMasterTableView:, but the selector in the notification code is reloadMasterTable:. Is one of those a typo? – danh May 16 '12 at 02:35
  • @Joel I confirmed just with break points. – Crystal May 16 '12 at 02:47
  • @mohabitar I did a search for the addObserver and I'm only adding in viewDidLoad the one time. So unless the viewDidLoad gets called twice, I believe the registering is only once. – Crystal May 16 '12 at 02:47
  • @danh Yes that was a typo. The breakpoint is at on the reloadMasterTable: – Crystal May 16 '12 at 02:48
  • Best to confirm with log. Sometimes stepping through the code can be unreliable as the line numbers can get out of sync between the debugger and compiled code. – Joel May 16 '12 at 02:54
  • Also, are you removing the observer in viewDidUnload? Personally I do not like registering/unregistering observers in viewDidLoad/viewDidUnload as it could unregister during a low memory situation when you still want it listening. I prefer to register/unregister in init and dealloc. – Joel May 16 '12 at 02:56
  • After placing a breakpoint at reloadMasterTable: method. In the debug navigation, select By Threads and look at current threads stacktrace ( or bt in gdb ). Look at it first time code hits that breakpoint and second time. You'll be able to figure out what happened. ( otherwise post the stacktrace here ) – 0x8badf00d May 16 '12 at 02:57
  • viewDidLoad can be called multiple times on the same view controller instance... – Joel May 16 '12 at 02:59
  • @Joel, Why would a viewDidLoad gets called twice? I have never seen that happening or read anywhere in the documentation. Can you please provide any reference ? – 0x8badf00d May 16 '12 at 03:02
  • If a view is unloaded it must be reloaded. See Aaron's answer here. http://stackoverflow.com/questions/3949935/when-is-viewdidload-called You generally want your observer tied to the lifecycle or your UIViewController instance (init/dealloc), not tied to the view's lifecycle (intuitively that doesn't make a lot of sense). – Joel May 16 '12 at 03:11
  • @0x8badf00d this might be a better explanation: http://stackoverflow.com/questions/1081131/viewdidload-getting-called-twice-on-rootviewcontroller-at-launch – Joel May 16 '12 at 03:19
  • @Joel That's right. viewDidLoad can be called multiple times if it gets destroyed. I was thinking you got confused between viewDidAppear getting called twice when view is drawn onto screen. So in his case unregistering in viewDidUnload should work fine. – 0x8badf00d May 16 '12 at 03:24
  • Unless you want the view controller to keep listening regardless of the state of its view. And I believe it's a her not a his. :) – Joel May 16 '12 at 03:32

1 Answers1

0

I think a better way to implement this is by implementing the delegate pattern.

In your detail controller .h define a protocol

@protocol PillDetailViewControllerDelegate <NSObject>

- (void)PillDetailViewController:(PillDetailViewController *)vc didUpdatePillAtIndexPath:(NSIndexPath)indexpath;

@end

And add the delegate property

@property (nonatomic, assign) id<PillDetailViewControllerDelegate>delegate;

In your detail controller .m,

@synthesize delegate;

and instead of posting your notification in updateMasterTableView do:

[self.delegate PillDetailViewController:self didUpdatePillAtIndexPath:path];

Finally in your MasterView controller, set the set the delegate and respond to the callback

Hope this helps

iTukker
  • 2,083
  • 2
  • 16
  • 16