Search code examples
iosobjective-ciphonekey-value-coding

observeValueForKeyPath called multiple times


I have a custom container navigation. I have a diary view controller and a diary detail view controller. When user clicks on a picture in diary, it goes to diary detail using cycleFromViewController:toViewController method as described in the Apple docs about container view controllers.

When the detail view loads, I want the container view controller to remove one of it's subviews and add another one. I use KVC to accomplish this. It's my first time using KVC. addObserver method is in viewWillAppear in diary detail vc.

Problem: diary detail VC is loaded, observeValueForKeypath is called once the first time, twice the second time, and so on. Additionally, in observeValueForKeypath, I add a subview - UIButton - and when it is clicked, cycleFromViewController:toViewController is called again and the previous subview is added back. It works on the first go around, but on subsequent ones, the original subview is not added back, the UIButton just sticks around.

Diary Detail.m

-(void)viewWillAppear:(BOOL)animated{

[self addObserver:self.parentViewController forKeyPath:@"didLoadNumber" options:0 context:nil];

[self setValue:[NSNumber numberWithInt:0] forKey:@"didLoadNumber"];}

Main Container VC (observer/parent VC)

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{


    NSLog(@"KVO called");
    [self.usernameLabel removeFromSuperview];
    self.backButton = [[UIButton alloc]initWithFrame:CGRectMake(12, 28, 28, 28)];


    self.backButton.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.backButton];

    [self.backButton addTarget:self action:@selector(removeButtonAndAddLogo)
              forControlEvents:UIControlEventTouchUpInside];

}

-(void)removeButtonAndAddLogo{

NSLog(@"got to remove button");
[self.backButton removeFromSuperview];
self.usernameLabel = [[UILabel alloc]initWithFrame:CGRectMake(12, 28, 28, 28)];
self.usernameLabel.text = @"username";
self.usernameLabel.textColor = [UIColor blackColor];
[self.view addSubview:self.usernameLabel];

[self cycleFromViewController:self.diaryViewController.diaryDetailVC toViewController:self.diaryViewController];

}


Solution

  • For this you need to remove it in viewWillDisappear method. If you will come at this view controller more then one time , it'll register this notification again and again and whenever you call this notification it'll call multiple time(number of time's you have register it).

    -(void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        [self addObserver:self.parentViewController forKeyPath:@"didLoadNumber" options:0 context:nil];
        [self removeObserver:self.parentViewController forKeyPath:@"didLoadNumber"];
    }
    

    i hope it will help you.