Martin Herman
Martin Herman

Reputation: 888

Update UILabel text when a NSString is changed in another class

I have a NSObject class with NSStrings and UIImages. I fill them by downloading data from a server. What I do in a manager class, I download a JSON and parse it into the NSObject to fill the basic NSString & UIImages. Then I launch a method in the NSObject's class to download the more complex data from another server and put the NSObject into a NSMutableDictionary. So what I end up with is a dictionary full of my NSObjects, with some data already downloaded and some data still downloading.

Then I try to feed the data of the NSObject into UILabels, and UIImageViews in another class (view controller). However, some of the data will probably still be loading so their so the UILabels would show up empty if for example the NSString that should fill it wouldn't be downloaded yet.

Now my question is, how can I change the UILabels's text again, once the NSString in it's NSObject class has been downloaded (re-set)? Basically I'd need to "observe" the NSObject's NSString's value from the UILabel's class. I've found something like this:

observeValueForKeyPath:ofObject:change:context

But I have no idea how to use it. I know I'd have to implement it in the UILabel's class, but how, and how do I set it to update the UILabel's text when it observes a change in the NSObject's NSString?

Also I've read something about a NSObjectController class, is it applicable here?

Thank you in advance!

Upvotes: 1

Views: 610

Answers (3)

Tobi
Tobi

Reputation: 5519

Basically you need to implement the following in your UILabel subclass:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"nameOfThePropertyInYourNSObjectSubclass"]) {
        id changedValue = [object valueForKeyPath:keyPath];
        //do what ever you want with it
    }
}

Also to register your NSObject subclass for KVO, you need to implement:

[self addObserver:yourUILabel forKeyPath:@"nameOfThePropertyOfYourString" options:NSKeyValueObservingOptionNew context:NULL];

Note that you also have to unregister the observer at the appropriate time (depending on your design):

[self removeObserver:yourUILabel forKeyPath:@"nameOfThePropertyOfYourString" context:NULL];

Also note, that, while KVO is a neat thing and quite useful in some cases, it's be no means a no brainer to choose it. Especially in your case I would recommend to use a callback instead. Fetching data from the network is best done in a background thread, in that case I would use a delegate pattern to inform your view controller, that new data is available and let the view controller take care of updating your labels.

Upvotes: 1

Sulthan
Sulthan

Reputation: 130092

KVO is possible, but also check out delegate pattern. I believe it would be simpler here.

Upvotes: 0

Tim
Tim

Reputation: 60110

You're very close - what you want is called key-value observing, and it's described in detail in the Key-Value Observing Programming Guide. You don't need an NSObjectController for this - instead, have the view controller managing the view for the UILabels add itself as an observer for the other class, then just update the UILabel text whenever you receive the observeValueForKeyPath:ofObject:change:context message.

Upvotes: 1

Related Questions