Swift - Assign a NIB to self in class

后端 未结 2 1581
无人及你
无人及你 2021-01-06 10:00

I am creating a UIView subclass for a notification dropdown banner. I am using a XIB to build out the view and want to assign that xib to the class when it initializes (i.e.

相关标签:
2条回答
  • 2021-01-06 10:12

    For anyone looking on how to initialize a xib from it's own class in swift, here is the best approach using a custom class initializer:

    class MyCustomView: UIView
    {
        @IBOutlet weak var imageView: UIImageView!
        @IBOutlet weak var titleLabel: UILabel!
    
        class func initWithTitle(title: String, image: UIImage? = nil) -> MyCustomView
        {
            var myCustomView = UINib(nibName: "MyCustomView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as? MyCustomView
    
            myCustomView.titleLabel.text = title
    
            if image != nil
            {
                myCustomView.imageView.image = image
            }
    
            //...do other customization here...
            return myCustomView
        }
    }
    
    0 讨论(0)
  • 2021-01-06 10:17

    My usual approach is the following:

    1. Set my custom-view class as FileOwner in the nib
    2. Set all required outlets and actions
    3. Set outlet to the view in nib and name it 'contentView' in the class
    4. In the init* method - instantiate nib with owner and add subview to my custom-view object.

    Here is the example of the collection header view implemented this way.

    @interface Header : UITableViewHeaderFooterView
    
    @property (nonatomic) IBOutlet UIView *contentView;
    
    @property (weak, nonatomic) IBOutlet UILabel *labelTitle;
    // other required outlets & actions
    // ... 
    
    @end
    
    
    #import "Header.h"
    
    @implementation Header
    
    - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
    {
        if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
            [[NSBundle mainBundle] loadNibNamed:@"Header"
                                          owner:self
                                        options:nil];
            [self.contentView addSubview:self.content];
    
            UIView *subview = self.content;
            self.content.translatesAutoresizingMaskIntoConstraints  = NO;
            NSDictionary *viewsDictionary =  NSDictionaryOfVariableBindings(subview);
            [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[subview]|" options:0 metrics: 0 views:viewsDictionary]];
            [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[subview]|" options:0 metrics: 0 views:viewsDictionary]];
    
        }
        return self;
    }
    
    @end
    

    // UPDATE Swift example

    The main idea is not to load view from the nib directly to self but add it /view from nib/ as a subview to the self

    import UIKit
    
    class CustomView: UIView {
    
        @IBOutlet var contentView: UIView!
        @IBOutlet weak var labelTitle: UILabel!
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            self.__loadContent()
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.__loadContent()
        }
    
        private func __loadContent() {
            // create nib
            let nib = UINib(nibName: "CustomView", bundle: NSBundle.mainBundle())
            // load outlets to self
            nib.instantiateWithOwner(self, options: nil)
            // add content view as a subview
            self.addSubview(self.contentView)
            // disable autoresizing
            self.contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
            // manually create constraints to fix content view inside self with 0 padding
            let viewsDict: NSDictionary = ["content": self.contentView]
            let vertical = NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|",
                options: NSLayoutFormatOptions.allZeros,
                metrics: nil,
                views: viewsDict)
            let horizontal = NSLayoutConstraint.constraintsWithVisualFormat("H:|[content]|",
                options: NSLayoutFormatOptions.allZeros,
                metrics: nil, views: viewsDict)
            self.addConstraints(vertical)
            self.addConstraints(horizontal)
        }
    }
    

    InterfaceBuilder

    0 讨论(0)
提交回复
热议问题