I'm using Swift and Xcode 6.4 for what it's worth.
So I have a view controller that will be containing some multiple pairs of UILabels and UIImageViews. I wanted to put the UILabel-UIImageView pair into a custom UIView, so I could simply reuse the same structure repeatedly within the aforementioned view controller. (I'm aware this could be translated into a UITableView, but for the sake of ~learning~ please bear with me). This is turning out to be a more convoluted process than I imagined it would be, I'm having trouble figuring out the "right" way to make this all work in IB.
Currently I've been floundering around with a UIView subclass and corresponding XIB, overriding init(frame:) and init(coder), loading the view from the nib and adding it as a subview. This is what I've seen/read around the internet so far. (This is approximately it: http://iphonedev.tv/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6).
This gave me the problem of causing an infinite loop between init(coder) and loading the nib from the bundle. Strangely none of these articles or previous answers on stack overflow mention this!
Ok so I put a check in init(coder) to see if the subview had already been added. That "solved" that, seemingly. However I started running into an issue with my custom view outlets being nil by the time I try to assign values to them.
I made a didSet and added a breakpoint to take a look...they are definitely being set at one point, but by the time I try to, say, modify the textColor of a label, that label is nil. I'm kind of tearing my hair out here.
Reusable components seem like software design 101, but I feel like Apple is conspiring against me. Should I be looking to use container VCs here? Should I just be nesting views and having a stupidly huge amount of outlets in my main VC? Why is this so convoluted? Why do everyone's examples NOT work for me?
Desired result (pretend the whole thing is the VC, the boxes are the custom uiviews I want):
Thanks for reading.
Following is my custom UIView subclass. In my main storyboard, I have UIViews with the subclass set as their class.
class StageCardView: UIView {
@IBOutlet weak private var stageLabel: UILabel! {
didSet {
NSLog("I will murder you %@", stageLabel)
}
}
@IBOutlet weak private var stageImage: UIImageView!
var stageName : String? {
didSet {
self.stageLabel.text = stageName
}
}
var imageName : String? {
didSet {
self.stageImage.image = UIImage(named: imageName!)
}
}
var textColor : UIColor? {
didSet {
self.stageLabel.textColor = textColor
}
}
var splatColor : UIColor? {
didSet {
let splatImage = UIImage(named: "backsplat")?.tintedImageWithColor(splatColor!)
self.backgroundColor = UIColor(patternImage: splatImage!)
}
}
// MARK: init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if self.subviews.count == 0 {
setup()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
if let view = NSBundle.mainBundle().loadNibNamed("StageCardView", owner: self, options: nil).first as? StageCardView {
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
EDIT: Here's what I've been able to get so far...
XIB:
Result:
Problem: When trying to access label or image outlets, they are nil. When checking at breakpoint of said access, the label and image subviews are there and the view hierarchy is as expected.
I'm OK with doing this all in code if thats what it takes, but I'm not huge into doing Autolayout in code so I'd rather not if there's a way to avoid it!
EDIT/QUESTION SHIFT:
I figured out how to make the outlets stop being nil.
Inspiration from this SO answer: Loaded nib but the view outlet was not set - new to InterfaceBuilder except instead of assigning the view outlet I assigned the individual component outlets.
Now this was at the point where I was just flinging shit at a wall and seeing if it'd stick. Does anyone know why I had to do this? What sort of dark magic is this?