-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathNibLoadable.swift
115 lines (81 loc) · 3.35 KB
/
NibLoadable.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//
// NibLoadable.swift
// NibLoadable
//
// Created by Domas on 10/02/2017.
// Copyright © 2016 Trafi. All rights reserved.
//
import UIKit
/**
`NibLoadable` helps you reuse views created in .xib files.
# Reference only from code
Setup class by conforming to `NibLoadable`:
class MyView: UIView, NibLoadable {}
Get the view loaded from nib with a one-liner:
let myView = MyView.fromNib()
Setup like this will look for a file named "MyView.xib" in your project and load the view that is of type `MyView`.
*Optionally* provide custom nib name (defaults to type name):
class var nibName: String { return "MyCustomView" }
*Optionally* provide custom bundle (defaults to class location):
class var bundle: Bundle { return Bundle(for: self) }
# Refencing from IB
To reference view from another .xib or .storyboard file simply subclass `NibView`:
class MyView: NibView {}
If subclassing is **not an option** override `awakeAfter(using:)` with a call to `nibLoader`:
class MyView: SomeBaseView, NibLoadable {
open override func awakeAfter(using aDecoder: NSCoder) -> Any? {
return nibLoader.awakeAfter(using: aDecoder,
super.awakeAfter(using: aDecoder))
}
}
# @IBDesignable referencing from IB
To see live updates and get intrinsic content size of view reference simply subclass `NibView` with `@IBDesignable` attribute:
@IBDesignable
class MyView: NibView {}
If subclassing is **not an option** override functions of the view with calls to `nibLoader`:
@IBDesignable
class MyView: SomeBaseView, NibLoadable {
open override func awakeAfter(using aDecoder: NSCoder) -> Any? {
return nibLoader.awakeAfter(using: aDecoder, super.awakeAfter(using: aDecoder))
}
#if TARGET_INTERFACE_BUILDER
public override init(frame: CGRect) {
super.init(frame: frame)
nibLoader.initWithFrame()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
open override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
nibLoader.prepareForInterfaceBuilder()
}
open override func setValue(_ value: Any?, forKeyPath keyPath: String) {
super.setValue(value, forKeyPath: keyPath)
nibLoader.setValue(value, forKeyPath: keyPath)
}
#endif
}
*/
public protocol NibLoadable: class {
static var nibName: String { get }
static var bundle: Bundle { get }
}
// MARK: - From Nib
public extension NibLoadable where Self: UIView {
static var nibName: String {
return String(describing: self)
}
static var bundle: Bundle {
return Bundle(for: self)
}
static func fromNib() -> Self {
guard let nib = self.bundle.loadNibNamed(nibName, owner: nil, options: nil) else {
fatalError("Failed loading the nib named \(nibName) for 'NibLoadable' view of type '\(self)'.")
}
guard let view = (nib.first { $0 is Self }) as? Self else {
fatalError("Did not find 'NibLoadable' view of type '\(self)' inside '\(nibName).xib'.")
}
return view
}
}