Skip to content

Commit 50bd4da

Browse files
Add NoIBInspectable subspecs to fix XIB performance (#1232)
Co-authored-by: Luciano Almeida <passos.luciano@outlook.com>
1 parent d8da0c3 commit 50bd4da

11 files changed

+419
-323
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The changelog for **SwifterSwift**. Also see the [releases](https://github.com/S
88
- Added `addBottomSeparator(color:height:spacing:)` method to easily insert a bottom line to a view. 🚀 [#1234](https://github.com/SwifterSwift/SwifterSwift/pull/1234) by [sangjin](https://github.com/SsangG77)
99
- **Android**
1010
- Added Android platform support. [#1230](https://github.com/SwifterSwift/SwifterSwift/pull/1230) by [Marc Prud'hommeaux](https://github.com/marcprux)
11+
- **CocoaPods**
12+
- Added subspecs to not include `@IBInspectable` extensions, which can cause Xcode Interface Builder to run slowly. [#1323](https://github.com/SwifterSwift/SwifterSwift/pull/1323) by [guykogus](https://github.com/guykogus)
1113

1214
### Changed
1315
- **String**
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// NSViewInspectableExtensions.swift - Copyright 2025 SwifterSwift
2+
3+
#if canImport(AppKit) && !targetEnvironment(macCatalyst)
4+
import AppKit
5+
6+
public extension NSView {
7+
/// SwifterSwift: Border color of view; also inspectable from Storyboard.
8+
@IBInspectable
9+
var borderColor: NSColor? {
10+
get {
11+
guard let color = layer?.borderColor else { return nil }
12+
return NSColor(cgColor: color)
13+
}
14+
set {
15+
wantsLayer = true
16+
layer?.borderColor = newValue?.cgColor
17+
}
18+
}
19+
20+
/// SwifterSwift: Border width of view; also inspectable from Storyboard.
21+
@IBInspectable
22+
var borderWidth: CGFloat {
23+
get {
24+
return layer?.borderWidth ?? 0
25+
}
26+
set {
27+
wantsLayer = true
28+
layer?.borderWidth = newValue
29+
}
30+
}
31+
32+
/// SwifterSwift: Corner radius of view; also inspectable from Storyboard.
33+
@IBInspectable
34+
var cornerRadius: CGFloat {
35+
get {
36+
return layer?.cornerRadius ?? 0
37+
}
38+
set {
39+
wantsLayer = true
40+
layer?.masksToBounds = true
41+
layer?.cornerRadius = newValue.magnitude
42+
}
43+
}
44+
45+
/// SwifterSwift: Shadow color of view; also inspectable from Storyboard.
46+
@IBInspectable
47+
var shadowColor: NSColor? {
48+
get {
49+
guard let color = layer?.shadowColor else { return nil }
50+
return NSColor(cgColor: color)
51+
}
52+
set {
53+
wantsLayer = true
54+
layer?.shadowColor = newValue?.cgColor
55+
}
56+
}
57+
58+
/// SwifterSwift: Shadow offset of view; also inspectable from Storyboard.
59+
@IBInspectable
60+
var shadowOffset: CGSize {
61+
get {
62+
return layer?.shadowOffset ?? CGSize.zero
63+
}
64+
set {
65+
wantsLayer = true
66+
layer?.shadowOffset = newValue
67+
}
68+
}
69+
70+
/// SwifterSwift: Shadow opacity of view; also inspectable from Storyboard.
71+
@IBInspectable
72+
var shadowOpacity: Float {
73+
get {
74+
return layer?.shadowOpacity ?? 0
75+
}
76+
set {
77+
wantsLayer = true
78+
layer?.shadowOpacity = newValue
79+
}
80+
}
81+
82+
/// SwifterSwift: Shadow radius of view; also inspectable from Storyboard.
83+
@IBInspectable
84+
var shadowRadius: CGFloat {
85+
get {
86+
return layer?.shadowRadius ?? 0
87+
}
88+
set {
89+
wantsLayer = true
90+
layer?.shadowRadius = newValue
91+
}
92+
}
93+
94+
/// SwifterSwift: Background color of the view; also inspectable from Storyboard.
95+
@IBInspectable
96+
var backgroundColor: NSColor? {
97+
get {
98+
if let colorRef = layer?.backgroundColor {
99+
return NSColor(cgColor: colorRef)
100+
} else {
101+
return nil
102+
}
103+
}
104+
set {
105+
wantsLayer = true
106+
layer?.backgroundColor = newValue?.cgColor
107+
}
108+
}
109+
}
110+
111+
#endif

Sources/SwifterSwift/AppKit/NSViewExtensions.swift

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,6 @@ import AppKit
66
// MARK: - Properties
77

88
public extension NSView {
9-
/// SwifterSwift: Border color of view; also inspectable from Storyboard.
10-
@IBInspectable
11-
var borderColor: NSColor? {
12-
get {
13-
guard let color = layer?.borderColor else { return nil }
14-
return NSColor(cgColor: color)
15-
}
16-
set {
17-
wantsLayer = true
18-
layer?.borderColor = newValue?.cgColor
19-
}
20-
}
21-
22-
/// SwifterSwift: Border width of view; also inspectable from Storyboard.
23-
@IBInspectable
24-
var borderWidth: CGFloat {
25-
get {
26-
return layer?.borderWidth ?? 0
27-
}
28-
set {
29-
wantsLayer = true
30-
layer?.borderWidth = newValue
31-
}
32-
}
33-
34-
/// SwifterSwift: Corner radius of view; also inspectable from Storyboard.
35-
@IBInspectable
36-
var cornerRadius: CGFloat {
37-
get {
38-
return layer?.cornerRadius ?? 0
39-
}
40-
set {
41-
wantsLayer = true
42-
layer?.masksToBounds = true
43-
layer?.cornerRadius = newValue.magnitude
44-
}
45-
}
46-
479
// SwifterSwift: Height of view.
4810
var height: CGFloat {
4911
get {
@@ -54,71 +16,6 @@ public extension NSView {
5416
}
5517
}
5618

57-
/// SwifterSwift: Shadow color of view; also inspectable from Storyboard.
58-
@IBInspectable
59-
var shadowColor: NSColor? {
60-
get {
61-
guard let color = layer?.shadowColor else { return nil }
62-
return NSColor(cgColor: color)
63-
}
64-
set {
65-
wantsLayer = true
66-
layer?.shadowColor = newValue?.cgColor
67-
}
68-
}
69-
70-
/// SwifterSwift: Shadow offset of view; also inspectable from Storyboard.
71-
@IBInspectable
72-
var shadowOffset: CGSize {
73-
get {
74-
return layer?.shadowOffset ?? CGSize.zero
75-
}
76-
set {
77-
wantsLayer = true
78-
layer?.shadowOffset = newValue
79-
}
80-
}
81-
82-
/// SwifterSwift: Shadow opacity of view; also inspectable from Storyboard.
83-
@IBInspectable
84-
var shadowOpacity: Float {
85-
get {
86-
return layer?.shadowOpacity ?? 0
87-
}
88-
set {
89-
wantsLayer = true
90-
layer?.shadowOpacity = newValue
91-
}
92-
}
93-
94-
/// SwifterSwift: Shadow radius of view; also inspectable from Storyboard.
95-
@IBInspectable
96-
var shadowRadius: CGFloat {
97-
get {
98-
return layer?.shadowRadius ?? 0
99-
}
100-
set {
101-
wantsLayer = true
102-
layer?.shadowRadius = newValue
103-
}
104-
}
105-
106-
/// SwifterSwift: Background color of the view; also inspectable from Storyboard.
107-
@IBInspectable
108-
var backgroundColor: NSColor? {
109-
get {
110-
if let colorRef = layer?.backgroundColor {
111-
return NSColor(cgColor: colorRef)
112-
} else {
113-
return nil
114-
}
115-
}
116-
set {
117-
wantsLayer = true
118-
layer?.backgroundColor = newValue?.cgColor
119-
}
120-
}
121-
12219
/// SwifterSwift: Size of view.
12320
var size: CGSize {
12421
get {
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// UIButtonInspectableExtensions.swift - Copyright 2025 SwifterSwift
2+
3+
#if canImport(UIKit) && !os(watchOS)
4+
import UIKit
5+
6+
public extension UIButton {
7+
/// SwifterSwift: Image of disabled state for button; also inspectable from Storyboard.
8+
@IBInspectable
9+
var imageForDisabled: UIImage? {
10+
get { image(for: .disabled) }
11+
set { setImage(newValue, for: .disabled) }
12+
}
13+
14+
/// SwifterSwift: Image of highlighted state for button; also inspectable from Storyboard.
15+
@IBInspectable
16+
var imageForHighlighted: UIImage? {
17+
get { image(for: .highlighted) }
18+
set { setImage(newValue, for: .highlighted) }
19+
}
20+
21+
/// SwifterSwift: Image of normal state for button; also inspectable from Storyboard.
22+
@IBInspectable
23+
var imageForNormal: UIImage? {
24+
get { image(for: .normal) }
25+
set { setImage(newValue, for: .normal) }
26+
}
27+
28+
/// SwifterSwift: Image of selected state for button; also inspectable from Storyboard.
29+
@IBInspectable
30+
var imageForSelected: UIImage? {
31+
get { image(for: .selected) }
32+
set { setImage(newValue, for: .selected) }
33+
}
34+
35+
/// SwifterSwift: Image of focused state for button; also inspectable from Storyboard.
36+
@IBInspectable
37+
var imageForFocused: UIImage? {
38+
get { image(for: .focused) }
39+
set { setImage(newValue, for: .focused) }
40+
}
41+
42+
/// SwifterSwift: Title color of disabled state for button; also inspectable from Storyboard.
43+
@IBInspectable
44+
var titleColorForDisabled: UIColor? {
45+
get { titleColor(for: .disabled) }
46+
set { setTitleColor(newValue, for: .disabled) }
47+
}
48+
49+
/// SwifterSwift: Title color of highlighted state for button; also inspectable from Storyboard.
50+
@IBInspectable
51+
var titleColorForHighlighted: UIColor? {
52+
get { titleColor(for: .highlighted) }
53+
set { setTitleColor(newValue, for: .highlighted) }
54+
}
55+
56+
/// SwifterSwift: Title color of normal state for button; also inspectable from Storyboard.
57+
@IBInspectable
58+
var titleColorForNormal: UIColor? {
59+
get { titleColor(for: .normal) }
60+
set { setTitleColor(newValue, for: .normal) }
61+
}
62+
63+
/// SwifterSwift: Title color of selected state for button; also inspectable from Storyboard.
64+
@IBInspectable
65+
var titleColorForSelected: UIColor? {
66+
get { titleColor(for: .selected) }
67+
set { setTitleColor(newValue, for: .selected) }
68+
}
69+
70+
/// SwifterSwift: Title color of focused state for button; also inspectable from Storyboard.
71+
@IBInspectable
72+
var titleColorForFocused: UIColor? {
73+
get { titleColor(for: .focused) }
74+
set { setTitleColor(newValue, for: .focused) }
75+
}
76+
77+
/// SwifterSwift: Title of disabled state for button; also inspectable from Storyboard.
78+
@IBInspectable
79+
var titleForDisabled: String? {
80+
get { title(for: .disabled) }
81+
set { setTitle(newValue, for: .disabled) }
82+
}
83+
84+
/// SwifterSwift: Title of highlighted state for button; also inspectable from Storyboard.
85+
@IBInspectable
86+
var titleForHighlighted: String? {
87+
get { title(for: .highlighted) }
88+
set { setTitle(newValue, for: .highlighted) }
89+
}
90+
91+
/// SwifterSwift: Title of normal state for button; also inspectable from Storyboard.
92+
@IBInspectable
93+
var titleForNormal: String? {
94+
get { title(for: .normal) }
95+
set { setTitle(newValue, for: .normal) }
96+
}
97+
98+
/// SwifterSwift: Title of selected state for button; also inspectable from Storyboard.
99+
@IBInspectable
100+
var titleForSelected: String? {
101+
get { title(for: .selected) }
102+
set { setTitle(newValue, for: .selected) }
103+
}
104+
105+
/// SwifterSwift: Title of focused state for button; also inspectable from Storyboard.
106+
@IBInspectable
107+
var titleForFocused: String? {
108+
get { title(for: .focused) }
109+
set { setTitle(newValue, for: .focused) }
110+
}
111+
}
112+
113+
#endif
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// UITextFieldInspectableExtensions.swift - Copyright 2025 SwifterSwift
2+
3+
#if canImport(UIKit) && !os(watchOS)
4+
import UIKit
5+
6+
public extension UITextField {
7+
/// SwifterSwift: Left view tint color.
8+
@IBInspectable var leftViewTintColor: UIColor? {
9+
get {
10+
guard let iconView = leftView as? UIImageView else { return nil }
11+
return iconView.tintColor
12+
}
13+
set {
14+
guard let iconView = leftView as? UIImageView else { return }
15+
iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
16+
iconView.tintColor = newValue
17+
}
18+
}
19+
20+
/// SwifterSwift: Right view tint color.
21+
@IBInspectable var rightViewTintColor: UIColor? {
22+
get {
23+
guard let iconView = rightView as? UIImageView else { return nil }
24+
return iconView.tintColor
25+
}
26+
set {
27+
guard let iconView = rightView as? UIImageView else { return }
28+
iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
29+
iconView.tintColor = newValue
30+
}
31+
}
32+
}
33+
34+
#endif

0 commit comments

Comments
 (0)