Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView subclass in Swift: IBOutlet is found nil while unwrapping

I am trying to create a custom view in Swift by subclassing UIView, and I have a view board named MyViewPanel.xib that has its class assigned to MyCustomView. The implementation is as following:

import UIKit
@IBDesignable
class MyCustomView: UIView {
 @IBOutlet weak var title: UILabel!

 var question: Question {
     didSet {
        print("did set question, title is: \(question.title)")
     }
 }

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


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

override func drawRect(rect: CGRect) {
        let height = rect.height
        let width = rect.width
        let color: UIColor = UIColor.whiteColor()

        let drect = CGRect(x: (width * 0.25), y: (height * 0.25), width: (width * 0.5),height: (height * 0.5))
        let bpath: UIBezierPath = UIBezierPath(rect: drect)
        color.set()
        bpath.stroke()
    }

override func awakeFromNib() {
        super.awakeFromNib()
        print("awake from nib!")
        self.title.text = "Test title" // error: found nil while unwrapping an Optional Value 
    }
}

During the run time, I encountered the following error:

fatal error: unexpectedly found nil while unwrapping an Optional value

Since the awakeFromNib() is the first lifecycle event in UIView, I do not understand why the title UILabel is nil in this case.

Edit:

To use this custom view, I just draw a UIView rectangle on my storyboard and assign its class to MyCustomView. In the viewDidLoad() method of my ViewController for the storyboard, I set the question on the custom view:

override func viewDidLoad() {
   // myCustomView is an IBOutlet in the view controller
   myCustomView.question = question
}
like image 678
TonyGW Avatar asked Jan 09 '16 23:01

TonyGW


2 Answers

The code part looks OK but this would suggest the outlets have not been connected correctly in interface builder. In the outlets section in interface builder can you see the title outlet is connected and does not show an exclamation mark indicating an error. Also the IBOutlet line in the code should have a filled circle next to it to indicate the outlet is connected correctly and the class is correctly assigned from interface builder.

like image 181
Dallas Johnson Avatar answered Oct 20 '22 05:10

Dallas Johnson


I figured out how to set the text for a UILabel in a convenience initializer for a UIView subclass I wrote:

@IBOutlet weak var messageLabel: UILabel!

init?(frame: CGRect, message: String) {
    super.init(frame: frame)

    guard let view = NSBundle.mainBundle().loadNibNamed("MyViewSubclass", owner: self, options: nil).first as? MyViewSubclass else {
        return nil
    }

    // Without the following line, my view was always 600 x 600
    view.frame = frame

    self.addSubview(view)

    guard let messageLabel = view.messageLabel else {
        return
    }

    messageLabel.text = message
}
like image 23
Carl Smith Avatar answered Oct 20 '22 07:10

Carl Smith