简体   繁体   中英

How to “import” a UIView XIB into a UIViewController XIB?

I've seen a few answers here that seem to get at what I'm after, but I can't make any of them work.

MyView is a UIView subclass with a handful of images and text fields laid out and styled in MyView.xib and bound to IBOutlets in MyView.(h|m) . File's Owner is not set in the XIB, but MyView is the class of the top-level object. At runtime I dynamically load various MyViews into certain view controllers via NSBundle's loadNibNamed . Everything goes swimmingly.

But I have another view controller, MyVC , which at design time I would like to populate with a few instances of MyView. Following intuition, I laid out a UIView object in MyVC.xib with the same size as MyView, set its type to MyView , added an IBOutlet declaration in MyVC.h , and hooked up the connection.

When I run, MyVC shows no MyView . But debugging indicates that the connection is made, the view is indeed a MyView , and MyView's awakeFromNib does execute. And I'm sure that MyVC's MyView is on top of the hierarchy, because I set its background to a nice bright red. So where the devil is MyView ?

The simplest solution is to make MyView have a single subview, which is a container for the rest of its descendant views. This gives you a single point of contact between what's in MyVC.xib and what's in MyView.xib , and lets you connect outlets in both xibs.

In MyVC.xib , set the class of each placeholder view to MyView .

In MyView.xib , set the class of the top-level view to UIView . Set the class of File's Owner to MyView . If you have any outlets on MyView that were connected in MyView.xib , you will need to reconnect them to File's Owner since the top-level view no longer has those outlets.

In -[MyView initWithCoder:] , load MyView.xib and add its top-level view as your subview. Untested example:

+ (UINib *)nib {
    static dispatch_once_t once;
    static UINib *nib;
    dispatch_once(&once, ^{
        nib = [UINib nibWithNibName:NSStringFromClass(self) bundle:[NSBundle bundleForClass:self]];
    });
    return nib;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        NSArray *contents = [[self.class nib] instantiateWithOwner:self options:nil][0];
        UIView *containerView = contents[0];

        // Make sure the container view's size tracks my size.
        containerView.frame = self.bounds;
        containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        self.autoresizesSubviews = YES;
        if ([self respondsToSelector:@selector(setTranslatesAutoresizingMaskIntoConstraints:)]) {
            self.translatesAutoresizingMaskIntoConstraints = YES;
            containerView.translatesAutoresizingMaskIntoConstraints = YES;
        }
        // If you're using autolayout in both xibs, you should probably create
        // constraints between self and containerView here.

        [self addSubview:containerView];
    }
    return self;
}

This has the effect that you can connect MyView 's outlets to things in MyVC.xib and to things in MyView.xib , and you can connect the outlets of other objects in MyVC.xib and MyView.xib to the instance of MyView . However, you can't connect outlets of other objects in MyVC.xib to other objects in MyView.xib or vice versa.

ORIGINAL: override initWithCoder, a bad idea as the comment below says

NEW SUGGESTION:

  • create the MyVC view using the technique you have now (the MyView instances will essentially be empty views)

Then in the MyVC's viewDidLoad: method:

  • create new MyView instances using your nib, one for each of the ones in MyView

  • replace each of the empty (ie placeholder) MyViews with the ones you just created, making sure the frames are properly set (set any property/ivars, and use '- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2' to replace the old view with the new one in the subview array)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM