On 5 Jun 2014, at 3:03 pm, Rick Mann <[email protected]> wrote:
> I can solve this by doing an explicit UI update step in -viewDidLoad, but
> that ends up effectively duplicating the UI update code.
>
> I can load the view in -setFoo: by referencing self.view, but this seems like
> a hack.
>
> What are other people doing to address this? Any "best practice" you guys
> like?
I guess this is really a question about the timing of the -setFoo: call
relative to the -loadView call, and that would probably imply that calling
-setFoo: is actually the responsibility of a higher-level controller than this
one (probably the object that alloc/inits the view controller). So maybe you
could set up a simple informal delegate method such that the VC has the
higher-level controller as its delegate, and when -viewDidLoad: is called, it
asks the delegate to provide 'foo' at that time.
As far as observing 'foo' via KVO, the way I generally like to do this is to
have my VC implement methods that have the exact same form (as setters) as the
properties they're interested in on the model object, then my observer method
boils down to a very simple trampoline:
- (void) observeValueForKeyPath: ....
{
[self setValue:[changeDict objectForKey:NSKeyValueChangeNewKey]
forKey:keyPath];
}
This leverages the automatic unwrapping of property values that KVC already
does, so I don't have to do it again myself. This is so general I have it
wrapped up into a simple base class that all of these similar view controllers
subclass - each subclass then just adds the set<Key> : methods it needs.
For setting up and tearing down the KVO, I do as you do, but something that can
simplify this is to get the observed objects to vend a list of "observable
properties" that the observer can simply iterate over and add itself as an
observer for each one. This is typically a class method. The downside would be
that there may well be properties of no interest, but this approach implies you
still need a cover method for those properties, but of course you can also
override -setValue:forUndefinedKey: not to throw an exception but to ignore
instead. Otherwise, just observing the properties of interest one by one is
also fine. I have found though that by generalising the approach, if you have a
large number of similar but variant interfaces on a large number of similar but
variant model objects, it can generalise away a lot of the tedium. I've
actually found this approach a lot easier to live with than bindings, which
also claim to generalise the problem (as well as moving it into IB), but can be
opaque as a result.
In terms of setting up the initial state of the UI, provided -setFoo: is called
at the right time (after the view is loaded), then passing the
NSKeyValueObservingOptionInitial as a flag to the -addObserver: call ensures
that the same trampolining method is used both for initial setup and ongoing
changes to the model property.
As for tear-down at dealloc time, -setFoo:nil is fine, as it then tears down
the observation on the existing (retained) foo object prior to releasing it.
I've not run into issues with the unregistering observations error, at least
not since this was improved a lot a few OS versions back.
--Graham
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]