• 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
an interesting delegate design issue raised by IB...
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

an interesting delegate design issue raised by IB...


  • Subject: an interesting delegate design issue raised by IB...
  • From: "Michael B. Johnson" <email@hidden>
  • Date: Tue, 11 Sep 2001 21:56:24 -0700

so there are lots of places in the AppKit that one sees a delegate design pattern.

As a brief refresher, a delegate pattern is one where to use an instance of a class A you don't subclass class A, but rather derive a class B (or add to an existing class B) that conforms to a protocol and then you set an instance of class B to be the "delegate" of the class A.

Some obvious (and not so obvious ones) Appkit examples would be NSOutlineView, NSTableView, NSApplication, NSWindow, NSBrowser, NSColorPanel, NSComboBox, NSCustomImageRep, NSDrawer, NSFontPanel, NSImage,
NSInputServer, NSLayoutManager, NSMatrix, NSPageLayout, NSRulerView, etc.

My experience using delegation in the AppKit usually revolves around two cases, which I think of as long lived vs one shot (i.e. one where the delegate is set separately, and then used, vs asking the object to do one thing and giving it a delegate to use as an argument).

Both of these are from the perspective of the client developer implementing the delegate, rarely as one designing the class that will use delegation to accomplish its task.

so...

I've come up with a pretty generic class for viewing images (WK2DImageView)
. It's pretty full featured, letting you have multiple images (that you either composite together, or tile, or page through one at a time) with a background color, where you can zoom the image in or out, drag images in and out, change the gamma, make it fullscreen, etc.

One thing that comes to mind pretty quickly is that it makes sense for WK2DImageView to use a delegate to supply it with its images (i.e. something that conforms to the WK2DImagesHandler protocol). This is handy for several reasons:

- it separates out the management of the images that the view is *not* displaying to someone else

- it gets code out of the image viewing class (WK2DImageView), which theoretically shouldn't need to be subclassed most of the time (if I do my job right)

- it allows a large set of the same images to be shared among a set of views.


Because I'm me, I wouldn't dream of making this class unless I put it on an IB palette, which suddenly raises some interesting issues.

One thing that bugs me about most classes that need delegates is that I still have to write them, even if I'm using the class exactly what it was designed for. To deal with this, it seems prudent to supply a simple companion class (WK2DImagesSource) that can easily act as a delegate for any number of image views to supply them with images.

WK2DImagesSource, of course, is also on the same IB palette and the user can drag one out and then wire up any number of image views to it. WK2DImagesSources each have an IB inspector, and the user can drag images (or use the "add image..." button) to add images to them, and then at run time these will be viewable from any WK2DImageView that is using it as a delegate.

Also, we make WK2DImageView conform to the WK2DImagesSources protocol as well, so that other objects can, very naturally, add images to the image view directly, although what the WK2DImageView will actually do is immediately pass the message on to its delegate.

so, here's the conundrum (if anyone is still left with me):

The natural way you would want to add images to an instance of WK2DImageView in IB is to just drag an image on top of it, right? Most natural thing in the world...

except that it's using a delegate. Which isn't connected until you go into test interface mode, archive these objects out, init them from a coder and have their connections wired up. Which means that anything you drop on it is going to get dropped into the bit bucket, because at the point you drop it, that WK2DImageView has no delegate (since you've used IB to connect it, but that happens to some future instance, not this one).

So here's my idea:

a WK2DImageView has two instance variables, both of type WK2DImagesSource*
. One is also an IBOutlet (let's say it's called _imagesSource) so that a user sees it in IB, and the other is not (let's call it _myImagesSource). When the WK2DImageView gets init'ed, it makes/unarchives its own delegate (a WK2DImagesSource). Then when images gets dragged over it, it hands these off to its delegate, which happily stores them. Then when we archive this object, we archive this delegate (_myImagesSource), with its data. When we finally do our awakeFromNib, if _imagesSource is set, that means we've been wired up to use some other delegate. We politely have our _myImageSource delegate hand over its images to this third party delegate, and then release and set to nil our _myImageSource. If, on the other hand, the user has neglected to wire this instance to another _imagesSource, we're already fine, since all of our hand off routines look like this, where first priority is given to our "private delegate" (for want of a better term):

- (void)addImage:(NSImage*)image named:(NSString*)name
{
if (_myImagesSource) {
[_myImagesSource addImage:image named:name];
} else {
[_imagesSource addImage:image named:name];
}
return ;
}


So is this completely heinous? Is there an obvious better way to have my cake and eat it to without resorting to this dual instance variable chicanery? If so, I'd love to know it.

I'm actually kind of pleased with most of this solution, but I'm sure many of you (both people who've kept up :-)) are horrified... The big advantage I see is that it "just works" from the user (client developer) perspective - they can drop images on the WK2DImageView, they can wire it up to a separate/shared delegate, which has its own images, and everything "just works".

Comments?


--> Michael B. Johnson, Ph.D. -- email@hidden
--> Studio Tools, Pixar Animation Studios
--> http://xenia.media.mit.edu/~wave


  • Follow-Ups:
    • Re: an interesting delegate design issue raised by IB...
      • From: Ondra Cada <email@hidden>
  • Prev by Date: file - open recent
  • Next by Date: Re: Would Any Developers Use This?
  • Previous by thread: Re: file - open recent
  • Next by thread: Re: an interesting delegate design issue raised by IB...
  • Index(es):
    • Date
    • Thread