Skip to content

Instantly share code, notes, and snippets.

@ManWithBear
Created March 26, 2017 11:16
Show Gist options
  • Save ManWithBear/4b2238f6776f27548a0142fe681b53ca to your computer and use it in GitHub Desktop.
Save ManWithBear/4b2238f6776f27548a0142fe681b53ca to your computer and use it in GitHub Desktop.
Loading objects from Nib
// If you want to create some common way to load objects from nibs, you will probably try something like that:
protocol NibLoadable: class {
static func fromNib() -> Self?
static func nibName() -> String
}
extension NibLoadable {
static func nibName() -> String {
return String(describing: Self.self)
}
static func fromNib() -> Self? {
let nibContent = Bundle(for: Self.self).loadNibNamed(nibName(), owner: nil, options: nil)
return nibContent?.first { $0 is Self } as? Self
}
}
extension UIView: NibLoadable { }
// But oups!
// Method 'fromNib()' in non-final class 'UIView' must return `Self` to conform to protocol 'NibLoadable'
// So what happend?
// UIView and all of its subclasses are adopting the NibLoadable protocol. It means, for UIView, that there will be
// method static func fromNib() -> UIView?
// Every UIView's subclasses will inherit this method, but protocol confirmance inherited too and expect
// static func fromNib() -> ChildView? method. So any subclass will violate protocol confirmance.
// So, should I create this function by hands for every class I want to load from nib?
// No! Here another generic solution, but not so elegant as protocol with default implementation:
func loadFromNib<T: AnyObject>(named nibName: String = String(describing: T.self)) -> T? {
let nibContent = Bundle(for: T.self).loadNibNamed(nibName, owner: nil, options: nil)
return nibContent?.first { $0 is T } as? T
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment