iOS - How to initialize custom UIView with specifi

2019-06-02 16:23发布

I am wondering what is the cleanest way to initialize a custom UIView with a specific frame.

The UIView is designed from a XIB file.

Here is my implementation :

class CustomView : UIView {

    @IBOutlet var outletLabel: UILabel!

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupView()
    }

    public override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    private func setupView() {

        // Set text for labels
    }
}

Here is how I want to initialize it in my ViewController :

let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
let frame = CGRect(x: 0, y: 0, width: screenWidth - 50, height: 70)

let customView = CustomView.init(frame: frame)

But it is not working, I have a white UIView without any outlets.

And if I do this instead :

// Extension to UIView to load Nib
let customView : CustomView = UIView.fromNib()

I can see my view from XIB file, with its width/height used in the Interface Builder.

What is I want to load the view from XIB file BUT with specific frame ?

Am I missing something about initialization ?

2条回答
祖国的老花朵
2楼-- · 2019-06-02 16:56

You can have a NibLoading class like:

// NibLoadingView.swift
//source:https://gist.github.com/winkelsdorf/16c481f274134718946328b6e2c9a4d8
import UIKit

// Usage: Subclass your UIView from NibLoadView to automatically load a xib with the same name as your class

@IBDesignable
class NibLoadingView: UIView {

    @IBOutlet weak var view: UIView!

    override init(frame: CGRect) {
        super.init(frame: frame)
        nibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        nibSetup()
    }

    private func nibSetup() {
        backgroundColor = .clear

        view = loadViewFromNib()
        view.frame = bounds
        view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.translatesAutoresizingMaskIntoConstraints = true

        addSubview(view)
    }



    private func loadViewFromNib() -> UIView {
        let bundle = Bundle(for: type(of:self))
        let nib = UINib(nibName: String(describing: type(of:self)), bundle: bundle)
        let nibView = nib.instantiate(withOwner: self, options: nil).first as! UIView
        nibView.anchorAllEdgesToSuperview()
        return nibView
    }

}

extension UIView {
    func anchorAllEdgesToSuperview() {
        self.translatesAutoresizingMaskIntoConstraints = false
        if #available(iOS 9.0, *) {
            addSuperviewConstraint(constraint: topAnchor.constraint(equalTo: (superview?.topAnchor)!))
            addSuperviewConstraint(constraint: leftAnchor.constraint(equalTo: (superview?.leftAnchor)!))
            addSuperviewConstraint(constraint: bottomAnchor.constraint(equalTo: (superview?.bottomAnchor)!))
            addSuperviewConstraint(constraint: rightAnchor.constraint(equalTo: (superview?.rightAnchor)!))
        }
        else {
            for attribute : NSLayoutAttribute in [.left, .top, .right, .bottom] {
                anchorToSuperview(attribute: attribute)
            }
        }
    }

    func anchorToSuperview(attribute: NSLayoutAttribute) {
        addSuperviewConstraint(constraint: NSLayoutConstraint(item: self, attribute: attribute, relatedBy: .equal, toItem: superview, attribute: attribute, multiplier: 1.0, constant: 0.0))
    }

    func addSuperviewConstraint(constraint: NSLayoutConstraint) {
        superview?.addConstraint(constraint)
    }
}

Then your view will subclass the NibLoadingClass like:

class YourUIView: NibLoadingView {
    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Set your XIB class in File's Owner like: In this case it will be YourUIView

enter image description here

Then instantiate it:

let myView = YourUIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width-60, height: 170))
查看更多
在下西门庆
3楼-- · 2019-06-02 16:59

You can create custom class like this...

import UIKit

class CustomView: UIView {

class func mainView() -> CustomView {
    let nib = UINib(nibName: "nib", bundle: nil)
    let view = nib.instantiate(withOwner: self, options: nil).first as! CustomView
    return view
}

override init(frame: CGRect) {
    super.init(frame: frame)
    let view = CustomView.mainView()
    view.frame = frame
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


}

Initialize view where you want...

let view = CustomView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = UIColor.blue
self.view.addSubview(view)
查看更多
登录 后发表回答