Kludges when binding to 'value' of Menu Items

  • I'm beginning to think that, in general, using the 'value' bindings
    in main menu items is not very well supported and maybe not a good idea.

    Issue #1...

    My main menu has an item which reflects a boolean value (checkmark),
    bound to an attribute of the frontmost document via my document
    controller.  However, invoking will/did change was complicated
    because, besides observing changes in this document attribute, I also
    have to observe for possible changes in the frontmost document
    itself, and I can't find any "willChange" notification for the latter.

    I've gotten it working by remembering as an ivar the "previous"
    document, observing NSWindowDidBecomeMainNotification, and writing
    what seems like alot of code to detect changes, etc.  I don't like
    it.  In order to ^properly^ invoke willChangeValueForKey:, I would
    need to know ^beforehand^ when the frontmost document will change.
    Note that this is usually caused by the user activating a different
    window, something only Cocoa is aware of.  So I need something like...

    NSWindow^Will^BecomeMainNotification

    or, even better

    NSFrontmostDocumentWillChange
    NSFrontmostDocumentDidChange

    but I can't find any such things.  Are there any?

    Issue #2...

    Besides the above problem, there's also the issue that menu items
    need a dummy "target" to ever be enabled, even if their action is
    accomplished via bindings.  So I wire all their targets to this...

    - (IBAction)dummyAction:(id)sender {
    }

    (Binding 'enabled' to YES is not sufficient is not sufficient to
    overcome the requirement for a target.)

    Again, it works, but is there a less kludgey way to do this?

    Jerry Krinock
  • > Issue #1...
    >
    > My main menu has an item which reflects a boolean value (checkmark),
    > bound to an attribute of the frontmost document via my document
    > controller.  However, invoking will/did change was complicated
    > because, besides observing changes in this document attribute, I also
    > have to observe for possible changes in the frontmost document
    > itself, and I can't find any "willChange" notification for the latter.

      You can always bind to File's Owner (NSApplication) with the keypath
    of "mainWindow.windowController.document.myBooleanKey" ...

    > Issue #2...
    >
    > Besides the above problem, there's also the issue that menu items
    > need a dummy "target" to ever be enabled, even if their action is
    > accomplished via bindings.  So I wire all their targets to this...

      I'm not sure if I fully understand you, but you can connect the menu
    item to First Responder ... that will give you *a* target and
    depending on your app, it could be the frontmost document (or a text
    view selected therein). You need to read up on the responder chain for
    more details.

      If that's *not* what you meant, can you rephrase?

    --
    I.S.
  • On 2007 Oct, 16, at 6:37, I. Savant wrote:

    > You can always bind to File's Owner (NSApplication) with the keypath
    > of "mainWindow.windowController.document.myBooleanKey" ...

    Wow.  That would be really slick if it would work.  To test this,
    first I purposely misspelled myBooleanKey and immediately got a "not
    key-value compliant" error, as expected.  But after I spelled it
    correctly, I get weird errors when I try and switch or open a window,
    such as...

    *** -[NSNull identifier]: selector not recognized [self = 0xa080b040]
    *** Exception raised during posting of notification.  Ignored.
    exception: *** -[NSNull identifier]: selector not recognized [self =
    0xa080b040]
    *** [<SSDocChildWindow 0x15fb9700>
    removeObserver:<NSKeyValueObservationForwarder 0x3b3800>
    forKeyPath:@"windowController.document.browfile.displayHierarchy"]
    was sent to an object that has no observers.

    (Note: SSDocChildWindow is the subclass of NSWindow I use for my
    document windows, and myBooleanKey is 'displayHierarchy'.)

    I don't get any of those errors if I simply un-check that binding in
    Interface Builder.  It looks like it gets confused when it needs to
    start observing a different browfile due to a mainWindow change,
    thinking that it was observing the window at the beginning of the
    keyPath, instead of the 'browfile' at the end of the keyPath.

    Have you, I.S., or anyone ever seen such a clever binding through
    NSApp work?  (If it was in a sample project somewhere that would be
    great!)

    >> Issue #2...
    >>
    >> Besides the above problem, there's also the issue that menu items
    >> need a dummy "target" to ever be enabled, even if their action is
    >> accomplished via bindings.  So I wire all their targets to this...
    >
    > I'm not sure if I fully understand you, but you can connect the menu
    > item to First Responder ... that will give you *a* target and
    > depending on your app, it could be the frontmost document (or a text
    > view selected therein).

    I should have emphasized the 'action' within the target.  Sure, I can
    target First Responder (or AppController), but in either case I need
    to connect to and define an action within that target, and this
    action needs to do nothing, except smile pretty when the menu item is
    validated.  So I use  'dummyAction:(id)sender{}', and I was wondering
    if anyone knows a better way, since this looks like a kludge.
  • > Wow.  That would be really slick if it would work.  To test this,
    > first I purposely misspelled myBooleanKey and immediately got a "not
    > key-value compliant" error, as expected.  But after I spelled it
    > correctly, I get weird errors when I try and switch or open a window,
    > such as...

      Maybe it's best if you back up and explain exactly what you're
    trying to accomplish and how things are set up in your project (code
    as well). I use the mainWindow.windowController.document.whatever
    approach quite frequently for inspector palettes and such. As long as
    everything is 100% KVC/KVO compliant and every document type "handles"
    the bound key (even if it's a dummy), it works perfectly for me.

      Granted, I've never used it in conjunction with menu items. It's
    always just been easier to use the validation methods and
    -menuNeedsUpdate: ...

    --
    I.S.
  • On 2007 Oct, 16, at 10:52, I. Savant wrote:

    > Maybe it's best if you back up and explain exactly what you're
    > trying to accomplish and how things are set up in your project (code
    > as well).

    I'm trying to get the job done.  Let's move on...

    > I use the mainWindow.windowController.document.whatever
    > approach quite frequently for inspector palettes and such. As long as
    > everything is 100% KVC/KVO compliant

    Yes, I tried another menu item and yes it did work, but I have no
    idea where to begin on the errors with the other item that I reported
    yesterday.

    > and every document type "handles"
    > the bound key (even if it's a dummy), it works perfectly for me.

    Yes, that was another thing I was worried about but hadn't got there
    yet.

    > Granted, I've never used it in conjunction with menu items. It's
    > always just been easier to use the validation methods and
    > -menuNeedsUpdate: ...

    The above is the real answer.  What I've learned:

    Unless you're working on a science project and want to be the first
    to discover obscure bugs because you're doing something few people
    have done, don't use the 'value' binding in NSMenuItem.  Finding bugs
    is particularly thankless as an OS version is about to become
    obsolete ;)  Use menuNeedsUpdate: etc instead.  Simpler, you get
    compiler warnings, and when you consider all the will/
    didChangeValueForKey and redundant accessors that are become
    necessary to "support" bindings, the number of code lines is comparable.

    So I ripped out all the bindings, did it the old way  and now
    everything works.  Thanks again, I.S., and also D.S. who replied
    privately.

    Jerry Krinock
  • >> Maybe it's best if you back up and explain exactly what you're
    >> trying to accomplish and how things are set up in your project (code
    >> as well).
    >
    > I'm trying to get the job done.  Let's move on...

      First, I would *strongly* suggest not dismissing that type of
    request on a technical mailing list in the future. For others who
    aren't familiar with your project, such an overview may be the only
    way to provide that help. It may not have been meant that way, but
    your response came off as rude and dismissive, which is an effective
    means of having your thread ignored by those who might otherwise have
    been willing to help.

      Second, we *all* have jobs we need to just 'get done'. Your
    schedule, quite frankly, is your own problem. If you need the help and
    those you're asking need more information, your unwillingness to
    provide that information due to your tight schedule only hurts you.
    Remember, we're all volunteers (except the moderators, of course) and
    can't be bothered if you can't either.

      Third, though I suggested that you might have better luck abandoning
    Bindings altogether in this case, your original question was how to
    make it work *with* Bindings. I was trying to continue along those
    lines and there is not enough information to proceed in any helpful
    way, hence the request for a solid overview of your goal. I'm positive
    Bindings should work for you as advertised, it just seems like your
    overall approach is where the problem lay. An overview of your
    approach might have exposed the problem.

      In any case, I'm glad you found an effective solution that fits your
    tight schedule.

    --
    I.S.
  • On 10/17/07, I. Savant <idiotsavant2005...> wrote:
    > Remember, we're all volunteers (except the moderators, of course) and

      Okay, so I was once again reminded off-list that even the moderators
    are volunteers too. :-) I take exception to this since they work for
    Apple *and* moderate the list ... I view this as more of a "Dilbert"
    style "volunteer". ;-)

    --
    I.S.
  • On 2007 Oct, 17, at 6:49, I. Savant wrote:

    > your response came off as rude and dismissive,

    Sorry, I.S.  I didn't mean to be rude or dismissive.

    > I'm positive
    > Bindings should work for you as advertised, it just seems like your
    > overall approach is where the problem lay. An overview of your
    > approach might have exposed the problem.

    Yes, upon further investigation, I agree with you that it should
    work.  The reason I say this is that, later, I tried to bind
    something else along a related long.key.path and got that same error:

    -[NSNull identifier]: selector not recognized

    For the record, I believe that this error is a clue that one of the
    components of a long.key.path in a binding is not KVC.  I did isolate
    it to a particular component but after trying for some time was
    unable to fix it.  So I decided it would be easier to simply not use
    bindings this time.

    The next time I see that error, I may have better luck and/or need
    for bindings.

    Thanks again,

    Jerry
  • On Oct 21, 2007, at 1:01 AM, Jerry Krinock wrote:

    > Sorry, I.S.  I didn't mean to be rude or dismissive.
    >
      No problem.

    > -[NSNull identifier]: selector not recognized
    >
    > For the record, I believe that this error is a clue that one of the
    > components of a long.key.path in a binding is not KVC.

      I'm not entirely sure I'm right, but I'm going to say "not
    necessarily".

    > I did isolate it to a particular component but after trying for some
    > time was unable to fix it.  So I decided it would be easier to
    > simply not use bindings this time.
    >
      There are *many* cases where this ... well ... is the case. :-)
    It's not perfect and it's not a catch-all, but Bindings is incredibly
    flexible. In this case my nit was that the window controller /
    document path absolutely works for me, but I wasn't sure whether your
    own situation was really so special that it wouldn't. Of course it's
    entirely possible (and somewhat probable) that it was ...

      I use bindings for all simple cases, some more difficult cases, and
    pretty much no complex cases. Not gospel, but just my own experience.

    --
    I.S.
previous month october 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 31        
Go to today