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
}
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.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With