I've always used the loadNibNamed method for loading custom views into view controllers, but now i'm trying to avoid calling that method outside the custom view for making it more reusable so that if another person uses my custom view he only will need to instantiate the view without loadFromNib, for example:
var myView: MyView = MyView()
And adding this view to the view controller's view would be enough, the custom view will load the nib inside itself. I'm trying to do it in Swift, in ObjC I've found code like the one of this answer: UIView and initWithFrame and a NIB file. How can i get the NIB file loaded? But in swift I can't use the init used in the answer:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
//
[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
I have this method and it ends with an infinite loop:
override init(frame: CGRect) {
super.init(frame: frame)
self.loadFromNibNamed("MyView")
}
I've also tried adding another view inside MyView as a IBOutlet like the other answer says and using all the inits:
@IBOutlet var view: UIView!
override init() {
super.init()
NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
self.addSubview(self.view)
}
override init(frame: CGRect) {
super.init(frame: frame)
NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
self.addSubview(self.view)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("MediaPlayerView", owner: self, options: nil)
self.addSubview(self.view)
}
But still got the error of the infinite loop.
I can't find a good solution to that and it's driving me crazy!! Somebody can help me please? Thanks!
You're getting an infinite loop, because loadNibNamed(_,owner:,options:)
call an init
, so then try to load again the nib, and again an so on... Try this:
Swift 4
var contentView: UIView?
// MARK: Initializers
override init(frame: CGRect) {
super.init(frame: frame)
configureView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configureView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
configureView()
}
override func awakeFromNib() {
super.awakeFromNib()
configureView()
}
// MARK: Config Functions
func configureView() {
guard let view = defaultView() else { return }
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(view)
contentView = view
updateView()
}
func defaultView() -> UIView? {
// Create view from a nib with the same name
let nibName = String(describing: type(of: self))
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
What this code does, is load the view from the nib, an then adding it to a subview inside your view.
This will work also when adding your view on another xibs, add @IBDesignable
and it will become available
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