• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Bindings - registering change notification for multiple keys
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bindings - registering change notification for multiple keys


  • Subject: Re: Bindings - registering change notification for multiple keys
  • From: dreamcat7 <email@hidden>
  • Date: Wed, 2 Jul 2008 11:12:04 +0100

Hi,
Thank you for all of your comments Ken, very helpful.

On 2 Jul 2008, at 09:16, Ken Thomases wrote:
custom class (say, "Preferences") -- again, making the dictionary an implementation detail -- and making the keys into properties of the Preferences class. In either case, there should be not key path which directly accesses the NSMutableDictionary without going through a custom setter of your own making

Yes that's good advice - it would be better to make a Preferences object that handled all of the preferences data, and also the saving and loading operations. Then obj-c properties for the accessor methods. Thank you for pointing out these missing KVO/KVC functionalities of NSMutableDictionary. I shall be sure not to use it except for plist back-end.


Now, how to deal with all those properties? Well, do you really need for the set of properties to be dynamic, or is it in fact static and you're just annoyed by the size (and the attendant repetitive work)?

Yes - its really more about application maintainability than anything else. I dont want to break the ooc-encapsulation ideaology. And should not be necessary to re-declare the same variable names in multiple places. Ultimately, all these items are manipulated by the user interface through bindings in IB. Otherwise they could be encapsulated better as feature-oriented objects and would not need to be accessed from those IB-controls (NSSlider, NSButton, etc) as individually.


If you really need for there to be a dynamic set of properties, you can accomplish that using valueForUndefinedKey: and setValue:forUndefinedKey:. Basically, you have "virtual" properties -- they won't have proper individual accessors, but the above-named methods will be invoked whenever anything tries to access them via KVC, and in your implementations you can simulate their existence (by accessing the NSMutableDictionary which is part of your implementation, for example)

If i understand correctly what you say its actually possible to override that function for plist-type object ?


- setValue:(NSObject*) obj ForUndefinedKey: (NSString*) key
{
// If i have an internal representation of NSMutableDictionary for the .plist file
[self.myMutableDict_PlistStore setValue:obj ForKey: key];

// If property Key is written with a naming convention, e.g. prefixed with letters 'PTUI'
// We may might assume it is one of our UI Element keys. And we may include a handler for this weak type.
// We can to call our data store-class methods to implement the common repetitive functionality**
// e.g. [self savePlistStore]; or we cache the PlistStore and save it when application becomes idle.**
}


So to confirm it will be triggered whenever any other object tries to access or save an undeclared property ?
Its also likely that elsewhere in the code accessing these non- existent properties give rise to some compiler warnings (!! ).


However for a more complex UI and many IB controls / outlets it means fewer (1) places to repeat that complexity on the model-side.
Certain larger cocoa apps - could benefit by using this approach.


** and in real-world application i no longer need to wire all controls to target action "uiSateState". Then binding to the undefined key 'PTUI(ElementName)' is neater.
It is weak-typing, but allows dynamic UI elements. And more coherent - looking code. This [self savePlistStore] is equivalent to synthetic property anyPreferences ( which Ken describe also for dependantKeys method below).


A larger and more complex app (e.g. a drawing program with toolbars and draggable items, etc) - would be an option to consider. Or even to re-factor an existing app.
Mine isnt particularly big yet but I believe for that others on this list, they may get into trouble with lots of settings and want to use something like that.



Whether the set of properties is static or dynamic, it's troublesome to observe them all. One possible solution for that is to use a synthetic property which represents the state of the whole set of properties. This property exists solely so that clients of the class may watch for changes in this multi-property state. It has no meaningful value. That is, clients may observe it, but they'll never really care what its value is, only when it "changes".

Let's suppose you go the route of creating a Preferences class. In that case, let's call the synthetic property "anyPreferences". It's read-only, so we just need a simple getter:

-(id)anyPreferences
{
return self;
// The choice to return self is essentially arbitrary
// We could instead return a different NSObject each time: return [[[NSObject alloc] init] autorelease];
// That would guarantee that any attempt to compare the "old" and "new" values of this property would indicate a difference,
// but it could cause a spike in memory usage.
}


Now, classes can observe an instance of Preferences for changes in its "anyPreferences" property. But under what circumstance would they be notified of a change in that property? Well, the normal ones. Something should arrange for will/didChangeValueForKey: to be called on the instance of Preferences with @"anyPreferences" as the parameter.

In the case of a static set of properties, the best thing to do is implement +keyPathsForValuesAffectingAnyPreferences in the Preferences class and return a set of the names of all of those properties:

+keyPathsForValuesAffectingAnyPreferences
{
return [NSSet setWithObjects:@"debug", /* list the other preference names here... */, nil];

If i declared my properties in the Preferences class, maybe there's a way to dump those list in obj-c from the class object and use it here.
If not then it might be a workaround to subclass the NSObject class to find the list of properties that belong to it.



}

(If you're targeting Tiger, you would instead use +setKeys:triggerChangeNotificationsForDependentKey: to accomplish this same thing:

+(void) initialize
{
if (self == [Preferences class])
{
[self setKeys:[NSArray arrayWithObjects:@"debug", /* list the other preference names here... */, nil]
triggerChangeNotificationsForDependentKey:@"anyPreferences"];
}
}


)


I know this is a lot to take in. I'm verbose like that. Sorry. ;)

I hope it's helpful, though.

Cheers,
Ken




_______________________________________________

Cocoa-dev mailing list (email@hidden)

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:
This email sent to email@hidden


  • Follow-Ups:
    • Re: Bindings - registering change notification for multiple keys
      • From: Ken Thomases <email@hidden>
References: 
 >Bindings - registering change notification for multiple keys (From: dreamcat7 <email@hidden>)
 >Re: Bindings - registering change notification for multiple keys (From: Ken Thomases <email@hidden>)

  • Prev by Date: Re: Getting mouse moved events on overlay windows
  • Next by Date: Re: Date and Time Conversion with TimeZone
  • Previous by thread: Re: Bindings - registering change notification for multiple keys
  • Next by thread: Re: Bindings - registering change notification for multiple keys
  • Index(es):
    • Date
    • Thread