简体   繁体   中英

Be able to load xib from both Storyboard and ViewController

I'm trying to create the perfect solution to make a custom UIView subclass directly from code and in Storyboard . However, I didn't found any solution.

For an IBDesignable solution through storyboard, I followed this example http://supereasyapps.com/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6 and works perfectly.

But if I try to call this subclass through UIViewController by calling this Extension method:

extension UIView {
    class func loadFromNibNamed(nibNamed: String, bundle : NSBundle? = nil) -> UIView? {
        return UINib(
            nibName: nibNamed,
            bundle: bundle
        ).instantiateWithOwner(nil, options: nil)[0] as? UIView
    }
}

It crashes and says that misses this class is not key value coding-compliant for the key .

Has anybody found a solution to share with me for have both possibilities?

I need it because I should use this UIView in storyboard and also as UITableview SectionHeader

To preserve both cases, I preferred to write this inside my subclass declaration:

@IBDesignable class CustomView: UIView {

    var view: UIView!

    @IBOutlet weak var button: UIButton!
    @IBOutlet weak var label: UILabel!


    func xibSetup() {
        view = loadViewFromNib()
        view.frame = bounds
        view.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
        addSubview(view)
    }

    func loadViewFromNib() -> UIView {

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "CustomView", bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

        return view
    }


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

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

In this way I can see and add it inside my storyboard . In ViewForHeaderInSection method, I wrote this:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

let header = UIView()

let view:CustomView = CustomView(frame: CGRect(x: 0, y: 0, width:  self.view.frame.width, height: 30))

view.label.text = "header title: \(section)"

header.addSubview(view)


return header

}

And so it works ;)

Here's how you can use an xib in a view controller that is instantiated from storyboard (in your case as a section header of a UITableView ).

  1. Create an xib file, design your interface, and the necessary connections to of the UI elements with the IBOutlets in your swift file
  2. In viewDidLoad method of your view controller class (one that is instantiated from the storyboard)

     // Name your xib and swift class as Header let headerNib = UINib(nibName: "Header", bundle: nil) self.tableView.registerNib(headerNib, forHeaderFooterViewReuseIdentifier: "header") 
  3. Implement the UITableViewDelegate method viewForHeaderInSection

     func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("header") as! Header // Customise your header view here return header; } 

That's all you need to do.

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