iosuiviewxibaddsubviewloadnibnamed

Dynamically instantiating custom UIView's from XIB issue (what's wrong with this code)?


What is wrong with the following code, it's seems to have an endless loop. Initially comes through init:frame, to commonInit, but then the XIB loading line triggers entering again through init:coder etc.

Two areas of question:

a) How to instantiate probably to avoid this problem (i.e. want to use the XIB to layout, but then dynamically creating/position multiple of these on a parent view in code)

b) setting self.label.text is problematic as it seems self.label (a UILabel linked to the XIB) hasn't been setup at this point, hence is nil. So dynamically, when I want to create this little custom UIView via XIB, add it as a subclass, then immediately set a value of the label how do I do this?

import UIKit

class DirectionInfoView: UIView {

    @IBOutlet weak var label: UILabel!

    func commonInit() {
        let viewName = "DirectionInfoView"
        let view: DirectionInfoView = NSBundle.mainBundle().loadNibNamed(viewName, owner: self, options: nil).first as! DirectionInfoView  // <== EXC_BAD_ACCESS (code=2...)
        self.addSubview(view)
        view.frame = self.bounds

        self.label.text = "testing 123"
    }

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

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

}

Usage:

 let newInfoView = DirectionInfoView(frame: self.mapview.bounds)
 myexitingView.addSubview(newInfoView)

Solution

  • This seems to work:

    import UIKit
    
    class DirectionInfoView: UIView {
        @IBOutlet weak var label: UILabel!
    
        func commonInit() {
            self.layer.borderWidth = 5
            self.layer.cornerRadius = 25
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            commonInit()
        }
    
    }
    

    Usage:

    let directionInfoView : DirectionInfoView = NSBundle.mainBundle().loadNibNamed("DirectionInfoView", owner: self, options: nil).first as! DirectionInfoView
    mapview.addSubview(directionInfoView)
    directionInfoView.label.text = "It Worked!"