0

I am tracking a progress with a UIProgressView and I set an observer to the property I'm tracking.

I add the observer in the viewWillAppear, like this:

-(void)viewWillAppear:(BOOL)animated
{
    [self addObserver:self forKeyPath:@"progress" options:0 context:nil];
}

And when I remove the observer in the viewWillDisappear, like this:

-(void)viewWillDisappear:(BOOL)animated
{
    [self removeObserver:self forKeyPath:@"progress"];
}

And in the observeValueForKeyPath method I updated the progress view:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object   change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if([keyPath isEqualToString:@"progress"])
    {

        [self.progressView setProgress:self.progress animated:YES];
    }
}

Now when I leave this viewController and I return the observeValueForKeyPath is not being called and I don't get the progressView continuously updated.

The behavior of the progressView according to the code above is shown in this video: https://youtu.be/PVRT_Jjtdh4

abnerabbey
  • 125
  • 1
  • 10
  • Your code seems to observe your viewController by itself, in which there is no need to use KVO. That's expected if you don't leave the view, your progress view will be updated. What confuses people is in which case you have to concern about your progressView when you leave it's owner, thus the viewController. On the other hand, if your progressView is an outer view of viewController, what needs to observe the viewController is the progressView itself. – Lane Jun 21 '17 at 08:26

3 Answers3

0

Key-value coding (KVC) is a mechanism for accessing an object’s properties indirectly. In your case "progress" is the property of UIProgressView. But you have registered observer for the UIViewController object which doesn't have 'progress' as property.

Hence replace self with self.progressView

[self addObserver:self.progressView forKeyPath:@"progress" options:0 context:nil];

into

[self addObserver:self.progressView forKeyPath:@"progress" options:0 context:nil];

Also, do the same for detaching observer :

[self removeObserver:self.progressView forKeyPath:@"progress"];

byJeevan
  • 3,728
  • 3
  • 37
  • 60
  • That is not the problem. The problem is when I leave the view and I return, the observeValueForKeyPath is not called and the progress view is not updated. But everything goes well while I don't leave the view. – abnerabbey Jun 21 '17 at 03:03
0

Find updated answer with example. This will help you :

Here you have to register as an observer of the value at a key path relative to the receiver. Also you need to set option.

Use :

-(void)viewWillAppear:(BOOL)animated
{
   [[Receiver Instance] addObserver:self forKeyPath:@"progress" options:NSKeyValueObservingOptionNew 
context:nil];
}

-(void)viewWillDisappear:(BOOL)animated
{
     [[Receiver Instance] removeObserver:self forKeyPath:@"progress"];
}   

Rest is as it is. Here, [Receiver instance] is the instance of class where you value for defined object progress is changing.

Vinit Ingale
  • 381
  • 1
  • 4
  • 17
-1

Better to remove observer only after class is deallocated. So intsead of placing in viewWillDisappear:animated: you can do the same below :

-(void) dealloc {
      [self removeObserver:self forKeyPath:@"progress"]
      [super dealloc];
}
byJeevan
  • 3,728
  • 3
  • 37
  • 60