[ad_1]
I have already got a complete information about initializing views and controllers, however that one lacks a really particular case: making a customized view utilizing interface builder. 🤷♂️
Loading xib recordsdata
Utilizing the contents of a xib file is a reasonably rattling simple activity to do. You should utilize the next two strategies to load the contents (aka. the view hierarchy) of the file.
let view = UINib(
nibName: "CustomView",
bundle: .major
).instantiate(
withOwner: nil,
choices: nil
).first as! UIView
view.body = self.view.bounds
self.view.addSubview(view)
The snippet above will merely instantiate a view object from the xib file. You may have a number of root objects within the view hierarchy, however this time let’s simply decide the primary one and use that. I assume that in 99% of the instances that is what you may want with the intention to get your customized views. Additionally you possibly can prolong the UIView object with any of the options above to create a generic view loader. Extra on that later… 😊
This methodology is fairly easy and low cost, nevertheless there may be one little disadvantage. You may’t get named pointers (retailers) for the views, however just for the foundation object. If you’re placing design components into your display, that is positive, but when you might want to show dynamic information, you would possibly wish to attain out for the underlying views as nicely. 😃
Customized views with retailers & actions
So the right method to load customized views from xib recordsdata goes one thing like this:
Inside your customized view object, you instantiate the xib file precisely the identical manner as I informed you proper up right here. 👆 The one distinction is that you simply needn’t use the thing array returned by the strategies, however it’s important to join your view objects via the interface builder, utilizing the File’s Proprietor as a reference level, plus a customized container view outlet, that’ll comprise every little thing you want. 🤨
class CustomView: View {
@IBOutlet weak var containerView: UIView!
@IBOutlet weak var textLabel: UILabel!
override func initialize() {
tremendous.initialize()
let identify = String(describing: sort(of: self))
let nib = UINib(nibName: identify, bundle: .major)
nib.instantiate(withOwner: self, choices: nil)
self.addSubview(self.containerView)
self.containerView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.containerView.topAnchor.constraint(equalTo: self.topAnchor),
self.containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor),
self.containerView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
self.containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
])
}
}
So the initialize methodology right here is simply loading the nib file with the proprietor of self. After the loading course of completed, your outlet pointers are going to be stuffed with correct values from the xib file. There’s one last item that we have to do. Even the views from the xib file are “programmatically” related to our customized view object, however visually they are not. So we’ve so as to add our container view into the view hierarchy. 🤐
If you wish to use your customized view object, you simply need to create a brand new occasion from it – inside a view controller – and at last be at liberty so as to add it as a subview!
One phrase about bounds, frames aka. springs and struts: fucking UGLY! That is two phrases. They’re thought of as a foul apply, so please use auto format, I’ve a pleasant tutorial about anchors, they’re wonderful and studying them takes about quarter-hour. 😅
class ViewController: UIViewController {
weak var customView: CustomView!
override func loadView() {
tremendous.loadView()
let customView = CustomView()
self.view.addSubview(customView)
NSLayoutConstraint.activate([
customView.topAnchor.constraint(equalTo: self.view.topAnchor),
customView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
customView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
customView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
])
self.customView = customView
}
override func viewDidLoad() {
tremendous.viewDidLoad()
self.customView.textLabel.textual content = "Lorem ipsum"
}
}
That is it, now you’ve gotten a very working customized UIView object that hundreds a xib file with the intention to use it is contents. Wasn’t so dangerous, proper? 🤪
Another further factor. For those who do not wish to deal with views programmatically otherwise you merely do not wish to fiddle with the loadView
methodology, simply take away it completely. Subsequent put the @IBOutlet
key phrase proper earlier than your customized view class variable. Open your storyboard utilizing IB, then drag & drop a brand new UIView factor to your controller and join the customized view outlet. It ought to work like magic. 💫
I promised retailers and actions within the heading of this part, so let’s discuss just a little bit about IBActions. They work precisely the identical as you’d anticipate them with controllers. You may merely hook-up a button to your customized view and delegate the motion to the customized view class. If you wish to ahead touches or particular actions to a controller, you must use the delegate sample or go along with a easy block. 😎
Possession and container views
It’s potential to depart out all of the xib loading mechanism from the view occasion. We are able to create a set of extensions with the intention to have a pleasant view loader with a customized view class from a xib file. This manner you do not want a container view anymore, additionally the proprietor of the file may be overlooked from the sport, it is roughly the identical methodology as reusable cells for tables and collections created by Apple. 🍎
It is best to know that going this manner you possibly can’t use your default UIView init strategies programmatically anymore, as a result of the xib file will deal with the init course of. Additionally if you’re attempting to make use of this sort of customized views from a storyboard or xib file, you will not be capable to use your retailers, as a result of the correspondig xib of the view class will not be loaded. In any other case if you’re attempting to load it manyally you may run into an infinite loop and ultimately your app will crash like hell. 😈
import UIKit
extension UINib {
func instantiate() -> Any? {
return self.instantiate(withOwner: nil, choices: nil).first
}
}
extension UIView {
static var nib: UINib {
return UINib(nibName: String(describing: self), bundle: nil)
}
static func instantiate(autolayout: Bool = true) -> Self {
func instantiateUsingNib<T: UIView>(autolayout: Bool) -> T {
let view = self.nib.instantiate() as! T
view.translatesAutoresizingMaskIntoConstraints = !autolayout
return view
}
return instantiateUsingNib(autolayout: autolayout)
}
}
class CustomView: UIView {
@IBOutlet weak var textLabel: UILabel!
}
Similar to with desk or assortment view cells this time it’s important to set your customized view class on the view object, as an alternative of the File’s Proprietor. You must join your retailers and principally you are finished with every little thing. 🤞
To any extent further you must ALWAYS use the instantiate methodology in your customized view object. The excellent news is that the perform is generic, returns the right occasion sort and it is extremely reusable. Oh, btw. I already talked about the dangerous information… 🤪
There’s additionally yet one more method by overriding awakeAfter, however I might not depend on that resolution anymore. In a lot of the instances you possibly can merely set the File’s Proprietor to your customized view, and go along with a container, that is a protected wager. If in case you have particular wants you would possibly want the second method, however please watch out with that. 😉
[ad_2]