Setting up bindings using GC and properties

  • Hi,

    I've been trying to get the hang of this for the past several hours,
    but I still can't get it right:  What is the correct way to initialize
    (by which I mean set an initial value) for a binding in a project
    using garbage collection and properties?  I think I'm following the
    examples fairly well, but I keep on getting
    "__TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__" errors saying that my
    class isn't KVC-compliant for a given property.
    (By "the examples" I mean the sample code found in the documentation
    about properties in "The Objective-C 2.0 Programming Language"
    documentation; as well as two helpful sample projects posted by
    mmalc:  BindingsDocumentInspector and ToDos.)

    In my current project, I'm trying to bind an NSMutableDictionary to
    the "Content Dictionary" binding of an NSDictionaryController, using
    the model key path "serverStatus".  I've declared the dictionary  and
    its setters and getters with the following:

    NSMutableDictionary *serverStatus;    [.....]  @property(copy,
    readwrite) NSMutableDictionary *serverStatus;

    I tried two different kinds of implementations for the property:
    First I tried using @dynamic with my own mutableCopy setter method,
    but when that gave me the KVC compliance error I reverted back to
    @synthesize.  That again, gave me the same error.

    I'm initializing the dictionary in my init method... is that the
    right way to do it?  Here's what my init method looks like:

    - (id)init
    {
    self = [super init];
    if (self != nil) {
      // Need to create URL with current IP address and port number:
      NSURL *me = [NSURL URLWithString:[NSString stringWithFormat:@"http://
    %@:%i",[[NSHost currentHost] ipv4Address], 5432]];

      [self setServerStatus:[NSMutableDictionary
    dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],@"started",
    [NSMutableArray arrayWithCapacity:10],@"previousCommandsSent",
    me,@"myAddress", [NSMutableArray arrayWithCapacity:
    5],@"currentlyConnectedControllers", @"off",@"bonjourOnOff", nil]];

    }
    return self;
    }

    (-ipv4Address is from a category of NSHost.  It returns a string.)

    Each time I try to Build and Run the app, I get an exception that the
    class is not KVC-compliant for "bonjourOnOff".  The relevant text
    field's binding is to the dictionary controller in question, with
    controller key "selection", model key path "bonjourOnOff", and my own
    custom value transformer.  I've checked the spelling, and it looks
    like there are no mistakes there.

    Does anyone have any idea what I could be doing wrong here, or some
    guidance on what the right way is to initialize bindings under GC?
    (For example, right now I'm using an autoreleased
    NSMutableDictionary... should I be using an autoreleased one (I know
    the examples do), or just a nested alloc and init and let GC take care
    of the release, like the ToDos example does for value transformers?)
    I'm completely confused here.

    Thanks,

    Sam
  • I dont know the answer but have the same issue :) With the difference
    that my property is assign :)

    On Nov 3, 2007, at 6:52 AM, Sam Stigler wrote:

    > Hi,
    >
    > I've been trying to get the hang of this for the past several
    > hours, but I still can't get it right:  What is the correct way to
    > initialize (by which I mean set an initial value) for a binding in a
    > project using garbage collection and properties?  I think I'm
    > following the examples fairly well, but I keep on getting
    > "__TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__" errors saying that my
    > class isn't KVC-compliant for a given property.
    > (By "the examples" I mean the sample code found in the
    > documentation about properties in "The Objective-C 2.0 Programming
    > Language" documentation; as well as two helpful sample projects
    > posted by mmalc:  BindingsDocumentInspector and ToDos.)
    >
    > In my current project, I'm trying to bind an NSMutableDictionary to
    > the "Content Dictionary" binding of an NSDictionaryController, using
    > the model key path "serverStatus".  I've declared the dictionary
    > and its setters and getters with the following:
    >
    > NSMutableDictionary *serverStatus;    [.....]  @property(copy,
    > readwrite) NSMutableDictionary *serverStatus;
    >
    > I tried two different kinds of implementations for the property:
    > First I tried using @dynamic with my own mutableCopy setter method,
    > but when that gave me the KVC compliance error I reverted back to
    > @synthesize.  That again, gave me the same error.
    >
    > I'm initializing the dictionary in my init method... is that the
    > right way to do it?  Here's what my init method looks like:
    >
    > - (id)init
    > {
    > self = [super init];
    > if (self != nil) {
    > // Need to create URL with current IP address and port number:
    > NSURL *me = [NSURL URLWithString:[NSString
    > stringWithFormat:@"http://%@:%i",[[NSHost currentHost] ipv4Address],
    > 5432]];
    >
    > [self setServerStatus:[NSMutableDictionary
    > dictionaryWithObjectsAndKeys:[NSNumber
    > numberWithBool:NO],@"started", [NSMutableArray arrayWithCapacity:
    > 10],@"previousCommandsSent", me,@"myAddress", [NSMutableArray
    > arrayWithCapacity:5],@"currentlyConnectedControllers",
    > @"off",@"bonjourOnOff", nil]];
    >
    > }
    > return self;
    > }
    >
    > (-ipv4Address is from a category of NSHost.  It returns a string.)
    >
    > Each time I try to Build and Run the app, I get an exception that
    > the class is not KVC-compliant for "bonjourOnOff".  The relevant
    > text field's binding is to the dictionary controller in question,
    > with controller key "selection", model key path "bonjourOnOff", and
    > my own custom value transformer.  I've checked the spelling, and it
    > looks like there are no mistakes there.
    >
    > Does anyone have any idea what I could be doing wrong here, or some
    > guidance on what the right way is to initialize bindings under GC?
    > (For example, right now I'm using an autoreleased
    > NSMutableDictionary... should I be using an autoreleased one (I know
    > the examples do), or just a nested alloc and init and let GC take
    > care of the release, like the ToDos example does for value
    > transformers?)  I'm completely confused here.
    >
    >
    > Thanks,
    >
    > Sam
  • On Nov 2, 2007, at 10:52 PM, Sam Stigler wrote:

    > I've been trying to get the hang of this for the past several
    > hours, but I still can't get it right:  What is the correct way to
    > initialize (by which I mean set an initial value) for a binding in a
    > project using garbage collection and properties?
    >
    Exactly as you would with managed memory.
    GC is an orthogonal technology to bindings.

    > I think I'm following the examples fairly well, but I keep on
    > getting "__TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__" errors saying
    > that my class isn't KVC-compliant for a given property.
    >
    That's because the class in question is not...

    > The relevant text field's binding is to the dictionary controller in
    > question, with controller key "selection", model key path
    > "bonjourOnOff", and my own custom value transformer.  I've checked
    > the spelling, and it looks like there are no mistakes there.
    >
    Replicating what you did, the error message is likely to be something
    like:

    2007-11-03 05:21:52.075 Dictionary[661:10b]
    [<_NSControllerKeyValuePair 0x1774e0> valueForUndefinedKey:]: this
    class is not key value coding-compliant for the key bonjourOnOff.

    Note that it's reporting * _NSControllerKeyValuePair * isn't KVC
    compliant for...

    Per the documentation:
    "The arrangedObjects method returns an array of objects that implement
    the NSDictionaryControllerKeyValuePair informal protocol. User
    interface controls are bound to the arranged objects array using key
    paths such as: arrangedObjects.key (displays the key name),
    arrangedObjects.value (displays the value for the key), or
    arrangedObjects.localizedKey (displays the localized key name). See
    NSDictionaryControllerKeyValuePair Protocol Reference for more
    information."

    <http://developer.apple.com/documentation/Cocoa/Reference/NSDictionaryContro
    ller_Class/Introduction/Introduction.html
    >

    so 'selection' will return the currently-selected key-value pair, with
    keys defined by the NSDictionaryControllerKeyValuePair protocol.

    If you want to display the value for bonjourOnOff, bind to [File's
    Owner].serverStatus.bonjourOnOff

    (assuming that File's Owner is the object for which you gave the init
    method).

    mmalc
  • Oh, I see... thanks!  I didn't realize it was a subclass of
    NSArrayController; I was going under the assumption its selection
    binding was the same as that for NSObjectController (which from
    reading the documentation I now realize wouldn't have made sense even
    if it was true).

    I fixed my binding as per your suggestion, and have now fixed the
    problem.

    Thanks again,

    Sam

    On Nov 3, 2007, at 5:37 AM, mmalc crawford wrote:

    [..........]
    >
    > Per the documentation:
    > "The arrangedObjects method returns an array of objects that
    > implement the NSDictionaryControllerKeyValuePair informal protocol.
    > User interface controls are bound to the arranged objects array
    > using key paths such as: arrangedObjects.key (displays the key
    > name), arrangedObjects.value (displays the value for the key), or
    > arrangedObjects.localizedKey (displays the localized key name). See
    > NSDictionaryControllerKeyValuePair Protocol Reference for more
    > information."
    >
    > <http://developer.apple.com/documentation/Cocoa/Reference/NSDictionaryContro
    ller_Class/Introduction/Introduction.html
    > >
    >
    >
    >
    > so 'selection' will return the currently-selected key-value pair,
    > with keys defined by the NSDictionaryControllerKeyValuePair protocol.
    >
    >
    >
    > If you want to display the value for bonjourOnOff, bind to [File's
    > Owner].serverStatus.bonjourOnOff
    >
    > (assuming that File's Owner is the object for which you gave the
    > init method).
    >
    >
    >
    > mmalc
    >
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today