views:

148

answers:

2

I'm making an app that includes the same group of buttons in many different contexts. The buttons send their actions to a different object in each context. I'd like to be able to design a single NSView in IB containing the buttons, and then be able to put copies of that view in many places in my nibs, while maintaining the link, so changes propagate. I'd like to connect each of those instances to different objects, and have the buttons send their actions to whatever object their parent view is connected to.

I thought of creating a subclass of NSView which, when loaded, replaces itself with another view which it loads from a nib file, setting the connected object as File's Owner, but I'm not convinced this is the cleanest method. Here's my implementation of that idea (which -does- work):

@implementation AVNViewFromNib

- (void)awakeFromNib
{
    //Load the nib whose name is specified by the "nibFile" key
    NSNib* viewNib = [[NSNib alloc] initWithNibNamed:[self valueForKey:@"nibFile"] bundle:[NSBundle mainBundle]];
    NSMutableArray* topLevelObjects = [NSMutableArray new];
    [viewNib instantiateNibWithOwner:relatedObject topLevelObjects:&topLevelObjects];

    //Find our replacement view in that nib
    for (id currentObject in topLevelObjects)
    {
        if ([currentObject isKindOfClass:NSClassFromString(@"AVNReplacementView")])
        {
            representedView = currentObject;
            break;
        }
    }

    //Copy appropriate properties from us to our representedView
    [representedView setAutoresizingMask:[self autoresizingMask]];
    [representedView setFrame:[self frame]];
    [[self superview] addSubview:representedView];

    //We were never here. :)
    [self removeFromSuperview];
    [viewNib autorelease];
}

@end

@implementation AVNReplacementView
@end

Is that the cleanest method? Is there a standard way of going about this?

A: 

Take a look at the Interface Builder Plug-in Programming Guide. I'm pretty sure this kind of thing is exactly what the IB plugin framework is for.

Noah Witherspoon
In "Deciding When to Create a Plug-In", I unfortunately answer "yes" to all three of the questions whose answers should be "no".("Are your custom objects going to be used by only one application?""Do your custom objects rely on state information found only in your application?""Would it be problematic to encapsulate your custom views in a standalone library or framework?")
andyvn22
+1  A: 

You can create the view with the buttons in it in IB, then drag that view into the Library window and save it. The catch is, there's no “link” between them; editing one won't change anything about the others.

If you want that, you'll need to make a subclass of NSView instead.

I thought of creating a subclass of NSView which, when loaded, replaces itself with another view which it loads from a nib file, setting the connected object as File's Owner, but I'm not convinced this is the cleanest method.

That could work. I don't think that's really all that dirty; the reason init methods return an object is that they explicitly can return a different object. However, I'm not sure how you'd handle views of different frames, since the loaded view will have whatever frame it has in the nib.

Another way would be to load the buttons from a nib, but you'd have to adjust their frames before adding them as subviews.

Peter Hosey