I have a base class called DesignableControl
. I use it in my custom views so that I can see them rendered in the storyboard. Here is the base class:
public class DesignableControl: UIControl {
private var view: UIView!
override public init(frame: CGRect) {
super.init(frame: frame)
configureViewForStoryboard()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configureViewForStoryboard()
}
func configureViewForStoryboard() {
if let nibView = NSBundle(forClass: self.dynamicType).loadNibNamed("\(self.dynamicType)", owner: self, options: nil).first as? UIView {
view = nibView
} else {
Log("Error loading view for storyboard preview. Couldn't find view named \(self.dynamicType)")
view = UIView()
}
view.frame = bounds
view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
backgroundColor = .clearColor()
addSubview(view)
}
}
Here is my subclass StackedButton
:
class StackedButton: DesignableControl {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var imageViewHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var imageViewWidthConstraint: NSLayoutConstraint!
@IBOutlet weak var label: UILabel!
...
}
The code above runs and looks fine when I run the application, however, when I view it in a storyboard, it crashes the Interface Builder process with EXC_BAD_ACCESS
on the following line in DesignableControl
(broken out for clarity):
func configureViewForStoryboard() {
let bundle = NSBundle(forClass: self.dynamicType)
print("bundle: \(bundle)")
let nibArray = bundle.loadNibNamed("\(self.dynamicType)", owner: self, options: nil)
print("nibArray: \(nibArray)") //<-- EXC_BAD_ACCESS
...
}
When I first wrote this code, it used to work, but seems to be broken in the latest version of Xcode (7.2.1 as of this post). What am I doing wrong?
Update:
The code started crashing when run, because the view wasn't getting set up properly. It turns out that the stack overflow issue was a red herring. There was a bug in a subclass in some
@IBDesignable
properties that were accessing@IBOutlets
before they were set. This was the root problem.Before:
After:
Original Answer:
Stack overflow™!!!
loadNibNamed()
was calling one of the constructors, which was callingconfigureViewForStoryboard()
, which was calling one of the constructors, which was callingconfigureViewForStoryboard()
.I removed the call to
configureViewForStoryboard()
frominit?(coder aDecoder: NSCoder)
and it seems to work now.