Skip to content

Commit 26c493d

Browse files
authored
Merge pull request #165 from 0xLeif/develop
Added Later (v2.0.0)
2 parents b0f6b26 + 374328e commit 26c493d

18 files changed

+406
-142
lines changed

.github/workflows/swift.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ jobs:
99
strategy:
1010
matrix:
1111
destination: ['platform=iOS Simulator,OS=13.1,name=iPhone 8']
12-
xcode: ['/Applications/Xcode_11.1.app/Contents/Developer']
12+
xcode: ['/Applications/Xcode_11.6.app/Contents/Developer']
1313
steps:
1414
- uses: actions/checkout@v1
1515
# Github Actions' machines do in fact have recent versions of Xcode,
1616
# but you may have to explicitly switch to them. We explicitly want
1717
# to use Xcode 11, so we use xcode-select to switch to it.
1818
- name: Switch to Xcode 11
19-
run: sudo xcode-select --switch /Applications/Xcode_11.1.app
19+
run: sudo xcode-select --switch /Applications/Xcode_11.6.app
2020
# Since we want to be running our tests from Xcode, we need to
2121
# generate an .xcodeproj file. Luckly, Swift Package Manager has
2222
# build in functionality to do so.

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
/*.xcodeproj
55
xcuserdata/
66
build
7+
*.resolved

Package.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@ let package = Package(
1414
dependencies: [
1515
// Dependencies declare other packages that this package depends on.
1616
// .package(url: /* package url */, from: "1.0.0"),
17+
.package(url: "https://github.com/0xLeif/Later", from: "0.3.0")
1718
],
1819
targets: [
1920
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
2021
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
2122
.target(
2223
name: "SwiftUIKit",
23-
dependencies: []),
24+
dependencies: [
25+
"Later"
26+
]),
2427
.testTarget(
2528
name: "SwiftUIKitTests",
2629
dependencies: ["SwiftUIKit"]),

Sources/SwiftUIKit/Containers/HStack.swift

+37-16
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,26 @@
66
//
77

88
import UIKit
9+
import Later
910

1011
/// Horizontal StackView
1112
@available(iOS 9.0, *)
1213
public class HStack: UIView {
14+
deinit {
15+
views.resign()
16+
}
17+
18+
private var spacing: Float
19+
private var padding: Float
20+
private var alignment: UIStackView.Alignment
21+
private var distribution: UIStackView.Distribution
1322
/// The views that the HStack contains
14-
public var views: [UIView] = []
23+
public lazy var views = Contract<[UIView]>(initialValue: [])
24+
.onChange { [weak self] (views) in
25+
Later.main {
26+
self?.draw(views: views ?? [])
27+
}
28+
}
1529

1630
/// Create a HStack
1731
/// - Parameters:
@@ -25,14 +39,13 @@ public class HStack: UIView {
2539
alignment: UIStackView.Alignment = .fill,
2640
distribution: UIStackView.Distribution = .fill,
2741
_ closure: () -> [UIView]) {
28-
views = closure()
42+
self.spacing = spacing
43+
self.padding = padding
44+
self.alignment = alignment
45+
self.distribution = distribution
2946
super.init(frame: .zero)
30-
31-
hstack(withSpacing: spacing,
32-
padding: padding,
33-
alignment: alignment,
34-
distribution: distribution,
35-
closure)
47+
views.value = closure()
48+
draw(views: views.value ?? [])
3649
}
3750

3851
/// Create a HStack that accepts an array of UIView?
@@ -47,18 +60,26 @@ public class HStack: UIView {
4760
alignment: UIStackView.Alignment = .fill,
4861
distribution: UIStackView.Distribution = .fill,
4962
_ closure: () -> [UIView?]) {
50-
views = closure()
51-
.compactMap { $0 }
63+
self.spacing = spacing
64+
self.padding = padding
65+
self.alignment = alignment
66+
self.distribution = distribution
5267
super.init(frame: .zero)
53-
54-
hstack(withSpacing: spacing,
55-
padding: padding,
56-
alignment: alignment,
57-
distribution: distribution)
58-
{ views }
68+
views.value = closure()
69+
.compactMap { $0 }
70+
draw(views: views.value ?? [])
5971
}
6072

6173
required init?(coder aDecoder: NSCoder) {
6274
fatalError("init(coder:) has not been implemented")
6375
}
76+
77+
internal func draw(views: [UIView]) {
78+
clear()
79+
.hstack(withSpacing: spacing,
80+
padding: padding,
81+
alignment: alignment,
82+
distribution: distribution)
83+
{ views }
84+
}
6485
}

Sources/SwiftUIKit/Containers/VStack.swift

+37-16
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,26 @@
66
//
77

88
import UIKit
9+
import Later
910

1011
/// Vertical StackView
1112
@available(iOS 9.0, *)
1213
public class VStack: UIView {
14+
deinit {
15+
views.resign()
16+
}
17+
18+
private var spacing: Float
19+
private var padding: Float
20+
private var alignment: UIStackView.Alignment
21+
private var distribution: UIStackView.Distribution
1322
/// The views that the VStack contains
14-
public var views: [UIView] = []
23+
public lazy var views = Contract<[UIView]>()
24+
.onChange { [weak self] (views) in
25+
Later.main {
26+
self?.draw(views: views ?? [])
27+
}
28+
}
1529

1630
/// Create a VStack
1731
/// - Parameters:
@@ -25,14 +39,13 @@ public class VStack: UIView {
2539
alignment: UIStackView.Alignment = .fill,
2640
distribution: UIStackView.Distribution = .fill,
2741
_ closure: () -> [UIView]) {
28-
views = closure()
42+
self.spacing = spacing
43+
self.padding = padding
44+
self.alignment = alignment
45+
self.distribution = distribution
2946
super.init(frame: .zero)
30-
31-
vstack(withSpacing: spacing,
32-
padding: padding,
33-
alignment: alignment,
34-
distribution: distribution,
35-
closure)
47+
views.value = closure()
48+
draw(views: views.value ?? [])
3649
}
3750

3851
/// Create a VStack that accepts an array of UIView?
@@ -47,18 +60,26 @@ public class VStack: UIView {
4760
alignment: UIStackView.Alignment = .fill,
4861
distribution: UIStackView.Distribution = .fill,
4962
_ closure: () -> [UIView?]) {
50-
views = closure()
51-
.compactMap { $0 }
63+
self.spacing = spacing
64+
self.padding = padding
65+
self.alignment = alignment
66+
self.distribution = distribution
5267
super.init(frame: .zero)
53-
54-
vstack(withSpacing: spacing,
55-
padding: padding,
56-
alignment: alignment,
57-
distribution: distribution)
58-
{ views }
68+
views.value = closure()
69+
.compactMap { $0 }
70+
draw(views: views.value ?? [])
5971
}
6072

6173
required init?(coder aDecoder: NSCoder) {
6274
fatalError("init(coder:) has not been implemented")
6375
}
76+
77+
internal func draw(views: [UIView]) {
78+
clear()
79+
.vstack(withSpacing: spacing,
80+
padding: padding,
81+
alignment: alignment,
82+
distribution: distribution)
83+
{ views }
84+
}
6485
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// UIAppearance+SwiftUIKit.swift
3+
//
4+
//
5+
// Created by Zach Eriksen on 8/25/20.
6+
//
7+
8+
import UIKit
9+
import Later
10+
11+
@available(iOS 9.0, *)
12+
public extension UIAppearance where Self: UIView {
13+
func contract<Value>(_ closure: (Self) -> Contract<Value>) -> ContractView<Self, Value> {
14+
ContractView(view: self) { view in
15+
closure(view)
16+
}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// UILabel+SwiftUIKit.swift
3+
// SwiftUIKit
4+
//
5+
// Created by Zach Eriksen on 7/7/20.
6+
//
7+
8+
import UIKit
9+
10+
public extension UILabel {
11+
@discardableResult
12+
func text(color: UIColor?) -> Self {
13+
textColor = color
14+
15+
return self
16+
}
17+
18+
@discardableResult
19+
func text(_ value: String?) -> Self {
20+
text = value
21+
22+
return self
23+
}
24+
}

Sources/SwiftUIKit/Extensions/UITextField+SwiftUIKit.swift

+7
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,11 @@ public extension UITextField {
1414

1515
return self
1616
}
17+
18+
@discardableResult
19+
func text(_ value: String?) -> Self {
20+
text = value
21+
22+
return self
23+
}
1724
}

Sources/SwiftUIKit/Extensions/UITextView+SwiftUIKit.swift

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ public extension UITextView {
1515
return self
1616
}
1717

18+
@discardableResult
19+
func text(_ value: String?) -> Self {
20+
text = value
21+
22+
return self
23+
}
24+
1825
@discardableResult
1926
func tint(color: UIColor?) -> Self {
2027
tintColor = color
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//
2+
// UIView+Later.swift
3+
// SwiftUIKit
4+
//
5+
// Created by Zach Eriksen on 8/26/20.
6+
//
7+
8+
import UIKit
9+
import Later
10+
11+
@available(iOS 9.0, *)
12+
public extension UIView {
13+
static func later(_ laterView: (Later.Type) -> LaterValue<UIView>) -> UIView {
14+
let view = UIView()
15+
16+
view.center {
17+
LoadingView()
18+
.start()
19+
}
20+
21+
laterView(Later.self)
22+
.whenSuccess { embeddedView in
23+
Later.main {
24+
view.clear()
25+
.embed {
26+
embeddedView
27+
}
28+
}
29+
30+
}
31+
32+
return view
33+
}
34+
35+
static func later(centeredLoadingView: UIView,
36+
withSize size: CGSize? = nil,
37+
_ laterView: (Later.Type) -> LaterValue<UIView>) -> UIView {
38+
39+
let view = UIView()
40+
41+
view.center {
42+
centeredLoadingView
43+
.configure {
44+
if let size = size {
45+
$0.frame(height: Float(size.height),
46+
width: Float(size.width))
47+
}
48+
}
49+
}
50+
51+
laterView(Later.self)
52+
.whenSuccess { embeddedView in
53+
Later.main {
54+
view.clear()
55+
.embed {
56+
embeddedView
57+
}
58+
}
59+
60+
}
61+
62+
return view
63+
}
64+
65+
static func later(embeddedLoadingView: UIView,
66+
withPadding padding: Float = 0,
67+
_ laterView: (Later.Type) -> LaterValue<UIView>) -> UIView {
68+
let view = UIView()
69+
70+
view.embed(withPadding: padding) {
71+
embeddedLoadingView
72+
}
73+
74+
laterView(Later.self)
75+
.whenSuccess { embeddedView in
76+
Later.main {
77+
view.clear()
78+
.embed {
79+
embeddedView
80+
}
81+
}
82+
83+
}
84+
85+
return view
86+
}
87+
}

0 commit comments

Comments
 (0)