Hier ist mein Objective-C-Code, den ich zum Laden einer Spitze für mein benutzerdefiniertes UIView
-Objekt verwende:
-(id)init{
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"myXib" owner:self options:nil];
return [subviewArray objectAtIndex:0];
}
Was ist der äquivalente Code in Swift?
Originallösung
.
class SomeView: UIView {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("SomeView", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
...
}
Beachten Sie, dass ich auf diese Weise eine Klasse bekomme, die sich von der Spitze lädt. Ich könnte SomeView dann als Klasse verwenden, wenn UIView im Projekt verwendet werden kann (im Interface-Builder oder programmgesteuert).
Update - mit der Swift 3-Syntax
Das Laden eines Xibs in der folgenden Erweiterung wird als Instanzmethode geschrieben, die dann von einem Initialisierer wie dem obigen verwendet werden kann:
extension UIView {
@discardableResult // 1
func fromNib<T : UIView>() -> T? { // 2
guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else { // 3
// xib not loaded, or its top view is of the wrong type
return nil
}
self.addSubview(contentView) // 4
contentView.translatesAutoresizingMaskIntoConstraints = false // 5
contentView.layoutAttachAll(to: self) // 6
return contentView // 7
}
}
Und die Aufrufermethode könnte so aussehen:
final class SomeView: UIView { // 1.
required init?(coder aDecoder: NSCoder) { // 2 - storyboard initializer
super.init(coder: aDecoder)
fromNib() // 5.
}
init() { // 3 - programmatic initializer
super.init(frame: CGRect.zero) // 4.
fromNib() // 6.
}
// other methods ...
}
Bildnachweis: Die Verwendung einer generischen Erweiterung in dieser Lösung wurde von Roberts Antwort unten inspiriert.
Edit Ändern von "view" in "contentView", um Verwirrung zu vermeiden. Der Array-Index wurde in ".first" geändert.
Mein Beitrag:
Swift 3/Swift 4
extension UIView {
class func fromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
}
}
Dann nennen Sie es so:
let myCustomView: CustomView = UIView.fromNib()
..oder auch:
let myCustomView: CustomView = .fromNib()
Hier ist eine Erweiterung, die Generics zum Laden eines UIView
aus einer Spitze verwendet
public extension UIView {
public class func fromNib(nibNameOrNil: String? = nil) -> Self {
return fromNib(nibNameOrNil, type: self)
}
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T {
let v: T? = fromNib(nibNameOrNil, type: T.self)
return v!
}
public class func fromNib<T : UIView>(nibNameOrNil: String? = nil, type: T.Type) -> T? {
var view: T?
let name: String
if let nibName = nibNameOrNil {
name = nibName
} else {
// Most nibs are demangled by practice, if not, just declare string explicitly
name = nibName
}
let nibViews = NSBundle.mainBundle().loadNibNamed(name, owner: nil, options: nil)
for v in nibViews {
if let tog = v as? T {
view = tog
}
}
return view
}
public class var nibName: String {
let name = "\(self)".componentsSeparatedByString(".").first ?? ""
return name
}
public class var nib: UINib? {
if let _ = NSBundle.mainBundle().pathForResource(nibName, ofType: "nib") {
return UINib(nibName: nibName, bundle: nil)
} else {
return nil
}
}
}
Ich bevorzuge das, da es keine zusätzlichen Einstellungen in der Spitze erfordert. Es basiert auf allgemeinen Namenskonventionen. Wenn Ihre Klasse CustomView
ist und mit einer Spitze mit dem Namen CustomView
übereinstimmt, können Sie Folgendes tun:
let myCustomView = CustomView.fromNib()
// or if you're unsure whether or not the nib exists
let myCustomView: CustomView? = CustomView.fromNib()
Wenn Sie aus irgendeinem Grund den Namen der Spitze angeben müssen, übergeben Sie eine Zeichenfolge arg:
let myCustomView = MyCustomView.fromNib("non-conventional-name")
Bekannte Probleme
Die Verwendung dieser Klasse mit einer privaten Ansichtsklasse scheint Probleme zu verursachen. Dies scheint ein systemweites Problem zu sein.
versuchen Sie folgenden Code.
var uiview :UIView?
self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView
Bearbeiten:
import UIKit
class TestObject: NSObject {
var uiview:UIView?
init() {
super.init()
self.uiview = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)[0] as? UIView
}
}
Ich habe dies mit Swift durch folgenden Code erreicht:
class Dialog: UIView {
@IBOutlet var view:UIView!
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = UIScreen.mainScreen().bounds
NSBundle.mainBundle().loadNibNamed("Dialog", owner: self, options: nil)
self.view.frame = UIScreen.mainScreen().bounds
self.addSubview(self.view)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Vergessen Sie nicht, Ihren XIB view outlet mit dem in Swift definierten view - Ausgang zu verbinden. Sie können First Responder auch auf Ihren benutzerdefinierten Klassennamen setzen, um weitere zusätzliche Ausgänge anzuschließen.
Hoffe das hilft!
Getestet in Xcode 7 Beta 4, Swift 2.0 und iOS9 SDK. Der folgende Code weist der uiview xib zu. . Sie können diese benutzerdefinierte Xib-Ansicht im Storyboard verwenden und auch auf das IBOutlet-Objekt zugreifen.
import UIKit
@IBDesignable class SimpleCustomView:UIView
{
var view:UIView!;
@IBOutlet weak var lblTitle: UILabel!
@IBInspectable var lblTitleText : String?
{
get{
return lblTitle.text;
}
set(lblTitleText)
{
lblTitle.text = lblTitleText!;
}
}
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib ()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib ()
}
func loadViewFromNib() {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: "SimpleCustomView", bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
view.frame = bounds
view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
self.addSubview(view);
}
}
Greifen Sie programmgesteuert auf customview zu
self.customView = SimpleCustomView(frame: CGRectMake(100, 100, 200, 200))
self.view.addSubview(self.customView!);
Quellcode - https://github.com/karthikprabhuA/CustomXIBSwift
Aufbauend auf den oben genannten Lösungen.
Dies funktioniert über alle Projektbündel hinweg und es sind keine Generika erforderlich, wenn fromNib () aufgerufen wird.
Swift 2
extension UIView {
public class func fromNib() -> Self {
return fromNib(nil)
}
public class func fromNib(nibName: String?) -> Self {
func fromNibHelper<T where T : UIView>(nibName: String?) -> T {
let bundle = NSBundle(forClass: T.self)
let name = nibName ?? String(T.self)
return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T()
}
return fromNibHelper(nibName)
}
}
Swift 3
extension UIView {
public class func fromNib() -> Self {
return fromNib(nibName: nil)
}
public class func fromNib(nibName: String?) -> Self {
func fromNibHelper<T>(nibName: String?) -> T where T : UIView {
let bundle = Bundle(for: T.self)
let name = nibName ?? String(describing: T.self)
return bundle.loadNibNamed(name, owner: nil, options: nil)?.first as? T ?? T()
}
return fromNibHelper(nibName: nibName)
}
}
Kann wie folgt verwendet werden:
let someView = SomeView.fromNib()
Oder so:
let someView = SomeView.fromNib("SomeOtherNibFileName")
Wenn Sie viele benutzerdefinierte Ansichten in Ihrem Projekt haben, können Sie Klassen wie UIViewFromNib
erstellen.
Swift 2.3
class UIViewFromNib: UIView {
var contentView: UIView!
var nibName: String {
return String(self.dynamicType)
}
//MARK:
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
//MARK:
private func loadViewFromNib() {
contentView = NSBundle.mainBundle().loadNibNamed(nibName, owner: self, options: nil)[0] as! UIView
contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
contentView.frame = bounds
addSubview(contentView)
}
}
Swift 3
class UIViewFromNib: UIView {
var contentView: UIView!
var nibName: String {
return String(describing: type(of: self))
}
//MARK:
override init(frame: CGRect) {
super.init(frame: frame)
loadViewFromNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadViewFromNib()
}
//MARK:
func loadViewFromNib() {
contentView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?[0] as! UIView
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.frame = bounds
addSubview(contentView)
}
}
In jeder Klasse, die nur von UIViewFromNib
erbt, können Sie auch die nibName
-Eigenschaft überschreiben, wenn die .xib
-Datei einen anderen Namen hat:
class MyCustomClass: UIViewFromNib {
}
Eine gute Möglichkeit, dies mit Swift zu tun, ist die Verwendung einer Aufzählung.
enum Views: String {
case view1 = "View1" // Change View1 to be the name of your nib
case view2 = "View2" // Change View2 to be the name of another nib
func getView() -> UIView {
return NSBundle.mainBundle().loadNibNamed(self.rawValue, owner: nil, options: nil)[0] as! UIView
}
}
Dann können Sie in Ihrem Code einfach Folgendes verwenden:
let view = Views.view1.getView()
Swift 4-Protokollerweiterungen
public protocol NibInstantiatable {
static func nibName() -> String
}
extension NibInstantiatable {
static func nibName() -> String {
return String(describing: self)
}
}
extension NibInstantiatable where Self: UIView {
static func fromNib() -> Self {
let bundle = Bundle(for: self)
let nib = bundle.loadNibNamed(nibName(), owner: self, options: nil)
return nib!.first as! Self
}
}
Annahme
class MyView: UIView, NibInstantiatable {
}
Diese Implementierung setzt voraus, dass die Nib den gleichen Namen wie die UIView-Klasse hat. Ex. MyView.xib. Sie können dieses Verhalten ändern, indem Sie nibName () in MyView implementieren, um einen anderen Namen als die Implementierung der Standardprotokollerweiterung zurückzugeben.
In der xib ist der Eigentümer der Dateien MyView und die Stammsichtklasse MyView.
Verwendungszweck
let view = MyView.fromNib()
Swift 3 Version von Logans Antwort
extension UIView {
public class func fromNib(nibName: String? = nil) -> Self {
return fromNib(nibName: nibName, type: self)
}
public class func fromNib<T: UIView>(nibName: String? = nil, type: T.Type) -> T {
return fromNib(nibName: nibName, type: T.self)!
}
public class func fromNib<T: UIView>(nibName: String? = nil, type: T.Type) -> T? {
var view: T?
let name: String
if let nibName = nibName {
name = nibName
} else {
name = self.nibName
}
if let nibViews = Bundle.main.loadNibNamed(name, owner: nil, options: nil) {
for nibView in nibViews {
if let tog = nibView as? T {
view = tog
}
}
}
return view
}
public class var nibName: String {
return "\(self)".components(separatedBy: ".").first ?? ""
}
public class var nib: UINib? {
if let _ = Bundle.main.path(forResource: nibName, ofType: "nib") {
return UINib(nibName: nibName, bundle: nil)
} else {
return nil
}
}
}
Ich bevorzuge diese Lösung (basierend auf der Antwort if @ GK100):
In SomeView.Swift habe ich die XIB in den Initialisierer init
oder init:frame: CGRect
geladen. Es ist nicht notwendig, "Selbst" etwas zuzuweisen. Sobald der XIB geladen ist, sind alle Ausgänge verbunden, einschließlich der Ansicht der obersten Ebene. Das einzige, was fehlt, ist das Hinzufügen der Draufsicht zur Ansichtshierarchie:
class SomeView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NSBundle.mainBundle().loadNibNamed("SomeObject", owner: self, options: nil)
self.addSubview(self.view); // adding the top level view to the view hierarchy
}
...
}
let subviewArray = NSBundle.mainBundle().loadNibNamed("myXib", owner: self, options: nil)
return subviewArray[0]
Hier ist eine saubere und deklarative Methode zum programmgesteuerten Laden einer Ansicht mithilfe einer Protokoll- und Protokollerweiterung (Swift 4.2):
protocol XibLoadable {
associatedtype CustomViewType
static func loadFromXib() -> CustomViewType
}
extension XibLoadable where Self: UIView {
static func loadFromXib() -> Self {
let nib = UINib(nibName: "\(self)", bundle: Bundle(for: self))
guard let customView = nib.instantiate(withOwner: self, options: nil).first as? Self else {
// your app should crash if the xib doesn't exist
preconditionFailure("Couldn't load xib for view: \(self)")
}
return customView
}
}
Und das kannst du so verwenden:
// don't forget you need a xib file too
final class MyView: UIView, XibLoadable { ... }
// and when you want to use it
let viewInstance = MyView.loadFromXib()
Einige zusätzliche Überlegungen :
Custom Class
der Ansicht (und die von dort festgelegten Ausgänge/Aktionen) festgelegt ist, nicht für den Dateieigentümer.Sie müssen lediglich die init-Methode in Ihrer UIView
-Klasse aufrufen.
Mach es so:
class className: UIView {
@IBOutlet var view: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
func setup() {
UINib(nibName: "nib", bundle: nil).instantiateWithOwner(self, options: nil)
addSubview(view)
view.frame = self.bounds
}
}
Wenn Sie diese Ansicht jetzt als Unteransicht im Ansichtscontroller hinzufügen möchten, tun Sie dies in der Ansichtscontroller.Swift-Datei folgendermaßen:
self.view.addSubview(className())
Swift 4
Vergessen Sie nicht, ".first as? CustomView" zu schreiben.
if let customView = Bundle.main.loadNibNamed("myXib", owner: self, options: nil)?.first as? CustomView {
self.view.addSubview(customView)
}
Wenn Sie irgendwo verwenden möchten
Die beste Lösung ist die Antwort von Robert Gummesson .
extension UIView {
class func fromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
}
}
Dann nennen Sie es so:
let myCustomView: CustomView = UIView.fromNib()
Sie können dies über das Storyboard tun, indem Sie nur die richtigen Einschränkungen für die Ansicht hinzufügen. Sie können dies ganz einfach tun, indem Sie eine beliebige Ansicht aus Ihrer eigenen Sicht subklassieren, sagen wir BaseView
:
Ziel c
BaseView.h
/*!
@class BaseView
@discussion Base View for getting view from xibFile
@availability ios7 and later
*/
@interface BaseView : UIView
@end
BaseView.m
#import "BaseView.h"
@implementation BaseView
#pragma mark - Public
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self prepareView];
}
return self;
}
#pragma mark - LifeCycle
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self prepareView];
}
return self;
}
#pragma mark - Private
- (void)prepareView
{
NSArray *nibsArray = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
UIView *view = [nibsArray firstObject];
view.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:view];
[self addConstraintsForView:view];
}
#pragma mark - Add constraints
- (void)addConstraintsForView:(UIView *)view
{
[self addConstraints:@[[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0],
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0]
]];
}
@end
Swift 4
import UIKit
class BaseView : UIView {
// MARK: - LifeCycle
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepareView()
}
override init(frame: CGRect) {
super.init(frame: frame)
prepareView()
}
internal class func xibName() -> String {
return String(describing: self)
}
// MARK: - Private
fileprivate func prepareView() {
let nameForXib = BaseView.xibName()
let nibs = Bundle.main.loadNibNamed(nameForXib, owner: self, options: nil)
if let view = nibs?.first as? UIView {
view.backgroundColor = UIColor.clear
view.translatesAutoresizingMaskIntoConstraints = false
addSubviewWithConstraints(view, offset: false)
}
}
}
UIView+Subview
public extension UIView {
// MARK: - UIView+Extensions
public func addSubviewWithConstraints(_ subview:UIView, offset:Bool = true) {
subview.translatesAutoresizingMaskIntoConstraints = false
let views = [
"subview" : subview
]
addSubview(subview)
var constraints = NSLayoutConstraint.constraints(withVisualFormat: offset ? "H:|-[subview]-|" : "H:|[subview]|", options: [.alignAllLeading, .alignAllTrailing], metrics: nil, views: views)
constraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: offset ? "V:|-[subview]-|" : "V:|[subview]|", options: [.alignAllTop, .alignAllBottom], metrics: nil, views: views))
NSLayoutConstraint.activate(constraints)
}
}
Ich biete zwei Varianten an, wie man Einschränkungen hinzufügt - üblich und innerhalb der Sprache des visuellen Formats - jede beliebige auswählen :)
Außerdem wird standardmäßig davon ausgegangen, dass xib
name denselben Namen wie der Name der Implementierungsklasse hat. Wenn nein, ändern Sie einfach den Parameter xibName
.
Wenn Sie Ihre Sicht von BaseView
subclassieren, können Sie leicht jede Ansicht einfügen und die Klasse in IB angeben.
Ich mache einfach so:
if let myView = UINib.init(nibName: "MyView", bundle: nil).instantiate(withOwner: self)[0] as? MyView {
// Do something with myView
}
In diesem Beispiel wird die erste Ansicht in der Spitze "MyView.xib" im Hauptpaket verwendet. Sie können jedoch entweder den Index, den Namen der Spitze oder das Bundle (standardmäßig main) ändern.
Früher habe ich Einblicke in die View-Init-Methode geweckt oder generische Methoden wie in den obigen Lösungen (die übrigens intelligent sind) erstellt, aber ich mache es nicht mehr.
Auf diese Weise kann ich unterschiedliche Layouts oder Merkmale verwenden, wobei die gleiche Ansichtslogik und derselbe Code beibehalten werden.
Ich finde es einfacher, ein Factory-Objekt (normalerweise der viewController, der die Ansicht verwendet) erstellen zu lassen, wenn es benötigt wird. Manchmal benötigen Sie einen Eigentümer (in der Regel, wenn die erstellte Ansicht mit dem Ersteller verbunden ist), manchmal nicht.
Das ist wahrscheinlich der Grund, warum Apple keine initFromNib
-Methode in seine UIView-Klasse aufgenommen hat ...
Um ein Beispiel aus dem Boden zu nehmen, wissen Sie nicht, wie Sie geboren werden. Du bist gerade geboren. So sind die Ansichten;)
Ähnlich wie einige der obigen Antworten, jedoch eine konsistentere Swift3 UIView-Erweiterung:
extension UIView {
class func fromNib<A: UIView> (nibName name: String, bundle: Bundle? = nil) -> A? {
let bundle = bundle ?? Bundle.main
let nibViews = bundle.loadNibNamed(name, owner: self, options: nil)
return nibViews?.first as? A
}
class func fromNib<T: UIView>() -> T? {
return fromNib(nibName: String(describing: T.self), bundle: nil)
}
}
Dies bietet den Komfort, die Klasse von einer selbst benannten Feder, aber auch von anderen Federn/Bündeln laden zu können.
class func loadFromNib<T: UIView>() -> T {
let nibName = String(describing: self)
return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)![0] as! T
}
Wenn Sie möchten, dass die Swift-UIView-Unterklasse vollständig in sich geschlossen ist und die Möglichkeit besteht, mit init oder init (frame :) instanziiert zu werden, ohne die Implementierungsdetails der Verwendung einer Nib preiszugeben, können Sie dies mit einer Protokollerweiterung tun. Diese Lösung vermeidet die verschachtelte UIView-Hierarchie, wie von vielen anderen Lösungen vorgeschlagen.
public class CustomView: UIView {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var valueLabel: UILabel!
public convenience init() {
self.init(frame: CGRect.zero)
}
public override convenience init(frame: CGRect) {
self.init(internal: nil)
self.frame = frame
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
fileprivate func commonInit() {
}
}
fileprivate protocol _CustomView {
}
extension CustomView: _CustomView {
}
fileprivate extension _CustomView {
// Protocol extension initializer - has the ability to assign to self, unlike
// class initializers. Note that the name of this initializer can be anything
// you like, here we've called it init(internal:)
init(internal: Int?) {
self = Bundle.main.loadNibNamed("CustomView", owner:nil, options:nil)![0] as! Self;
}
}
Die bequemste Implementierung. Hier benötigen Sie zwei Methoden, um direkt zum Objekt Ihrer Klasse zurückzukehren, nicht zu UIView.
extension UIView {
class var viewId: String {
return String(describing: self)
}
static func instance(from bundle: Bundle? = nil, nibName: String? = nil,
owner: Any? = nil, options: [AnyHashable : Any]? = nil) -> Self? {
return instancePrivate(from: bundle ?? Bundle.main,
nibName: nibName ?? viewId,
owner: owner,
options: options)
}
private static func instancePrivate<T: UIView>(from bundle: Bundle, nibName: String,
owner: Any?, options: [AnyHashable : Any]?) -> T? {
guard
let views = bundle.loadNibNamed(nibName, owner: owner, options: options),
let view = views.first(where: { $0 is T }) as? T else { return nil }
return view
}
}
Beispiel:
guard let customView = CustomView.instance() else { return }
//Here customView has CustomView class type, not UIView.
print(customView is CustomView) // true
Stärkere Version basierend auf Logans Antwort
extension UIView {
public class func fromNib(nibName: String? = nil) -> Self {
return fromNib(nibName: nibName, type: self)
}
public class func fromNib<T: UIView>(nibName: String? = nil, type: T.Type) -> T {
return fromNib(nibName: nibName, type: T.self)!
}
public class func fromNib<T: UIView>(nibName: String? = nil, type: T.Type) -> T? {
var view: T?
let name: String
if let nibName = nibName {
name = nibName
} else {
name = self.nibName
}
if let nibViews = nibBundle.loadNibNamed(name, owner: nil, options: nil) {
if nibViews.indices.contains(nibIndex), let tog = nibViews[nibIndex] as? T {
view = tog
}
}
return view
}
public class var nibName: String {
return "\(self)".components(separatedBy: ".").first ?? ""
}
public class var nibIndex: Int {
return 0
}
public class var nibBundle: Bundle {
return Bundle.main
}
}
Und du kannst gerne verwenden
class BaseView: UIView {
override class var nibName: String { return "BaseView" }
weak var delegate: StandardStateViewDelegate?
}
class ChildView: BaseView {
override class var nibIndex: Int { return 1 }
}