Search code examples
objective-cswiftimagecocoa-bindingsnsimageview

Binding valuePath to NSImageView causes NSImageView.image to return nil when dragging new images onto imagewell


I have a NSImageView which operates as an image well. It is also bound via. a value transformer using the value path property to display saved images for each record (the value transformer just appends the file path - I just store the image's file name in the database).

When I drag a image onto the image well when there is no value path bound (i.e. user haven't set the image yet) everything works well - scaling and setting the image in the database and then displaying the image. If there is already an image in the database displayed via. bindings dragging a new image onto the image well causes NSImageView.image to return nil. The image view itself is not nil.

I am capturing dragged images on the image well by setting a target and an action on the image well.

    imageWell.target         = self
    imageWell.action         = "imageWellAction:"

How can I access the dragged (new) image when another image is already bound to the NSImageView?


Solution

  • I spent a very long time deep in the bowels of NSPasteboard and a NSImageView subclass (trying to work through performDragOperation).

    The problem was caused by the NSValueTransformer not knowing what to do with the URLs that NSPasteboard was passing to it when it was bound and images were dropped onto it.

    In the end the easiest way to fix the situation was to add a NSImageView on top of the cocoa-bindings bound NSImageView. The topmost image view accepted drag operations, updated the managed object and then cleared its .image property. The bottom image view notices the managed object it is bound to is updated and then updates the image correctly.

    So:

    • top image view accepts drag & drops and then clears itself
    • bottom (obscured) image view is a cocoa-bindings image view only intended to display, not accept drag & drops.

    Ideally I'd be a NSValueTransformer ninja and know what to do to reverse-transform a dropped pasteboard url (which was always nil when a binding was present) but I chose pragmatism in this case.