I've created a custom UIView
with multiple IBOutlets including a UIImageView, and three UILabel
s. Despite setting the image value in the awakeFromNib() function, I'm still getting a nil value for the outlet when attempting to set it. The UIView
was constructed using a custom xib file.
I put the set operation in awakeFromNib()
so as to assure the outlets had been initialized prior to setting them, yet this failed to help. I'm not sure if it's an issue with the xib file as I've only ever used custom xibs when making a custom table cell, so perhaps the issue is rooted there?
class VotingCard: UIView {
@IBOutlet weak var proPicImg: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var hometownLabel: UILabel!
@IBOutlet weak var ratingLabel: UILabel!
var proPic = UIImage()
var name = ""
var hometown = ""
var rating = 0.0
init(pic: UIImage, rush: Rush) {
proPic = pic
name = rush.fullName
hometown = rush.homeTown
rating = rush.compositeRating
super.init(frame: CGRect(x: 0, y: 0, width: 250, height: 300))
}
override func awakeFromNib() {
proPicImg.image = proPic
nameLabel.text = name
hometownLabel.text = hometown
ratingLabel.text = "\(rating)"
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
I should view a simple card with the profile image and respective data visible, yet instead it crashes.
EDIT
NIB-based development is sort-of deprecated:
For iOS developers, using storyboards is the recommended way to design user interfaces.
But, looks like you're missing this step:
At runtime, you load a nib file using the method
loadNibNamed:owner:
or a variant thereof. The File's Owner is a placeholder in the nib file for the object that you pass as the owner parameter of that method. Whatever connections you establish to and from the File's Owner in the nib file in Interface Builder are reestablished when you load the file at runtime.
See as an example:
https://medium.com/@umairhassanbaig/ios-swift-creating-a-custom-view-with-xib-ace878cd41c5
If you want to do it the recommended way with Storyboard (apparently not, but this is for general audience):
viewDidLoad()—Called when the view controller's content view (the top of its view hierarchy) is created and loaded from a storyboard. The view controller's outlets are guaranteed to have valid values by the time this method is called. Use this method to perform any additional setup required by your view controller.
So with the UIViewController
method, put your code in viewDidLoad()
instead.
Keep in mind this is always called, so this will overwrite the work of your custom init()
function. Perhaps this is what you were running into.
I would refactor it to avoid ugly code. Create the Rush
object always (declare as Optional as stored property), but initialize it in awakeFromNib() for the XIB case, and copy the input object in the custom-init case.
Then viewDidLoad()
has no conditionals.
Your problem is either
1-The imageView isn't connected to Ib , and the fix is to connect it
Or
2- You create an object of the view with init(pic: UIImage, rush: Rush) {
and that for sure won't load the UI with view , hence all outlets are nil , and the fix to add this method
class func getInstance(_ pic: UIImage, rush: Rush) -> VotingCard {
let v = Bundle.main.loadNibNamed("VotingCard", owner: self, options: nil)!.first as! VotingCard
v.proPic = pic
v.name = rush.fullName
v.hometown = rush.homeTown
v.rating = rush.compositeRating
return v
}
Call
let v = VotingCard.getInstance(<#image#>,rush:<#rush#>)
v.frame = // set some frame
// ready for use
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.