Skip to content

Commit 31fa5eb

Browse files
committed
Add a view builder initializer to FetchedDataView
1 parent 9462fb0 commit 31fa5eb

9 files changed

Lines changed: 136 additions & 171 deletions

RELEASE_NOTES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ SwiftUIKit makes its best effort to honor semver, but breaking changes can occur
88

99
Thanks to [pnewell](https://github.com/pnewell), SwiftUIKit now supports Catalyst.
1010

11+
### ✨ Features
12+
13+
* The `FetchedDataView` has a new view-builder initializer.
14+
1115
### 🗑️ Deprecations
1216

17+
* The `CornerRadiusStyle` type has been deprecated.
18+
* The `CustomRoundedRectangle` view has been deprecated.
1319
* The `DateFormatter` init extensions have been deprecated.
1420
* The `DispatchQueue` `asyncAfter` extension has been deprecated.
21+
* The `FontStyle` type is no longer used and has been deprecated.
1522
* The `JsonEncoder/Decoder` date extensions have been deprecated.
1623
* The `View` `any()` extension should NOT be used and has been deprecated.
1724

Sources/SwiftUIKit/Styles/FontStyle.swift

Lines changed: 0 additions & 78 deletions
This file was deleted.

Sources/SwiftUIKit/Styles/ViewShadowStyle.swift

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,23 @@
88

99
import SwiftUI
1010

11-
/**
12-
This styles defines shadow values, to allow strong typing.
13-
14-
You can specify your own standard styles by creating static,
15-
calculated extension properties, for instance:
16-
17-
```swift
18-
extension ShadowStyle {
19-
20-
static let badge = Self(
21-
color: Color.black.opacity(0.1),
22-
radius: 3,
23-
x: 0,
24-
y: 2
25-
)
26-
}
27-
```
28-
29-
You can apply the style with the `.font(_ style:)` modifier.
30-
```
31-
*/
11+
/// This styles defines shadow types, to allow strong typing.
12+
///
13+
/// You can specify your own standard styles by creating new
14+
/// static properties, for instance:
15+
///
16+
/// ```swift
17+
/// extension ShadowStyle {
18+
/// static let badge = Self(
19+
/// color: Color.black.opacity(0.1),
20+
/// radius: 3,
21+
/// x: 0,
22+
/// y: 2
23+
/// )
24+
/// }
25+
/// ```
26+
///
27+
/// You can apply shadows with the `font(_ style:)` modifier.
3228
public struct ViewShadowStyle {
3329

3430
public init(

Sources/SwiftUIKit/Views/EditableView.swift

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@
99
#if os(iOS) || os(tvOS)
1010
import SwiftUI
1111

12-
/**
13-
This protocol simplifies checking and setting the edit mode.
14-
15-
Implement the protocol and add an `editMode` binding:
16-
17-
```swift
18-
@Environment(\.editMode)
19-
var editMode
20-
```
21-
22-
You can then check the edit mode state with `isEditing` and
23-
set it with `setIsEditing(_:)`.
24-
*/
12+
/// This protocol can be implemented by any view that should
13+
/// be able to toggle its edit mode.
14+
///
15+
/// To implement the protocol just add an `editMode` binding:
16+
///
17+
/// ```swift
18+
/// @Environment(\.editMode)
19+
/// var editMode
20+
/// ```
21+
///
22+
/// You can then check the edit mode with ``isEditing``, and
23+
/// set it with ``setIsEditing(_:)``.
2524
public protocol EditableView: View {
2625

2726
var editMode: Binding<EditMode>? { get }

Sources/SwiftUIKit/Views/FetchedDataView.swift

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,40 @@
88

99
import SwiftUI
1010

11-
/**
12-
This view can be used to present asynchronous data that can
13-
be in a loading, fetched or failed state.
14-
15-
By providing three views, the view will present the correct
16-
one depending on the state of the data:
17-
18-
* `content` is shown when `data` has a value.
19-
* `loadingView` is shown when `data` is nil and loading.
20-
* `noDataView` is shown when `data` is nil and not loading.
21-
22-
This lets you manage all three states of data fetching with
23-
a single view.
24-
*/
11+
/// This view can present asynchronous data that can be in a
12+
/// loading, fetched or failed state.
13+
///
14+
/// By providing three views, the view will show the correct
15+
/// one depending on the state of the data:
16+
///
17+
/// * `content` is shown when `data` has a value.
18+
/// * `loadingView` is shown when `data` is nil and loading.
19+
/// * `noDataView` is shown when `data` is nil and not loading.
20+
///
21+
/// This lets you manage all three states with a single view.
2522
public struct FetchedDataView<Model, Content: View, LoadingView: View, NoDataView: View>: View {
2623

24+
@available(*, deprecated, message: "Use the view builder-based initializer instead.")
2725
public init(
2826
data: Model?,
2927
isLoading: Bool,
3028
loadingView: LoadingView,
3129
noDataView: NoDataView,
32-
@ViewBuilder content: @escaping ContentBuilder
30+
@ViewBuilder content: @escaping (Model) -> Content
31+
) {
32+
self.data = data
33+
self.isLoading = isLoading
34+
self.loadingView = { loadingView }
35+
self.noDataView = { noDataView }
36+
self.content = { content($0) }
37+
}
38+
39+
public init(
40+
data: Model?,
41+
isLoading: Bool,
42+
@ViewBuilder loadingView: @escaping () -> LoadingView,
43+
@ViewBuilder noDataView: @escaping () -> NoDataView,
44+
@ViewBuilder content: @escaping (Model) -> Content
3345
) {
3446
self.data = data
3547
self.isLoading = isLoading
@@ -40,19 +52,17 @@ public struct FetchedDataView<Model, Content: View, LoadingView: View, NoDataVie
4052

4153
private let data: Model?
4254
private let isLoading: Bool
43-
private let loadingView: LoadingView
44-
private let noDataView: NoDataView
45-
private let content: ContentBuilder
46-
47-
public typealias ContentBuilder = (Model) -> Content
55+
private let loadingView: () -> LoadingView
56+
private let noDataView: () -> NoDataView
57+
private let content: (Model) -> Content
4858

4959
public var body: some View {
5060
if let data = data {
5161
content(data)
5262
} else if isLoading {
53-
loadingView
63+
loadingView()
5464
} else {
55-
noDataView
65+
noDataView()
5666
}
5767
}
5868
}
@@ -67,11 +77,21 @@ public struct FetchedDataView<Model, Content: View, LoadingView: View, NoDataVie
6777
let noDataView = Text("Preview.NoData")
6878

6979
var body: some View {
70-
Group {
71-
FetchedDataView(data: "Fetched data", isLoading: true, loadingView: loadingView, noDataView: noDataView, content: content)
72-
FetchedDataView(data: "Fetched data", isLoading: false, loadingView: loadingView, noDataView: noDataView, content: content)
73-
FetchedDataView(data: nilData, isLoading: true, loadingView: loadingView, noDataView: noDataView, content: content)
74-
FetchedDataView(data: nilData, isLoading: false, loadingView: loadingView, noDataView: noDataView, content: content)
80+
if #available(iOS 17.0, *) {
81+
FetchedDataView(
82+
data: nilData,
83+
isLoading: false,
84+
loadingView: { ProgressView() },
85+
noDataView: {
86+
ContentUnavailableView(
87+
"No data",
88+
systemImage: "x.circle"
89+
)
90+
.foregroundStyle(.red)
91+
}
92+
) { string in
93+
Text(string)
94+
}
7595
}
7696
}
7797
}

Sources/SwiftUIKit/Styles/CornerRadiusStyle.swift renamed to Sources/SwiftUIKit/_Deprecated/CornerRadiusStyle.swift

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,7 @@
88

99
import SwiftUI
1010

11-
/**
12-
This styles defines a corner radius, to allow strong typing.
13-
14-
You can specify your own standard styles by creating static,
15-
calculated extension properties, for instance:
16-
17-
```swift
18-
extension CornerRadiusStyle {
19-
20-
static let card = Self(radius: 5)
21-
}
22-
```
23-
24-
You can apply this style using the `.cornerRadius(_ style:)`
25-
view modifier.
26-
*/
11+
@available(*, deprecated, message: "This is no longer used and will be removed in the next major release.")
2712
public struct CornerRadiusStyle {
2813

2914
public init(radius: CGFloat) {
@@ -33,6 +18,7 @@ public struct CornerRadiusStyle {
3318
public let radius: CGFloat
3419
}
3520

21+
@available(*, deprecated, message: "This is no longer used and will be removed in the next major release.")
3622
public extension View {
3723

3824
/// Apply a ``CornerRadiusStyle`` to the view.

Sources/SwiftUIKit/Views/CustomRoundedRectangle.swift renamed to Sources/SwiftUIKit/_Deprecated/CustomRoundedRectangle.swift

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@
1010

1111
import SwiftUI
1212

13-
/**
14-
This shape can apply individual corner radii to each corner.
15-
16-
> Note: iOS 16 has an `UnevenRoundedRectangle` that in time
17-
will cause this view to become deprecated.
18-
*/
13+
@available(*, deprecated, message: "Use the native UnevenRoundedRectangle instead.")
1914
public struct CustomRoundedRectangle: Shape {
2015

2116
public init(
@@ -63,14 +58,17 @@ public struct CustomRoundedRectangle: Shape {
6358

6459
#Preview {
6560

66-
VStack {
67-
CustomRoundedRectangle(
68-
topLeft: 10,
69-
topRight: 20,
70-
bottomLeft: 30,
71-
bottomRight: 40
72-
)
73-
.foregroundColor(.red)
61+
if #available(iOS 16.0, *) {
62+
VStack {
63+
Color.red.clipShape(
64+
UnevenRoundedRectangle(cornerRadii: .init(
65+
topLeading: 10,
66+
bottomLeading: 30,
67+
bottomTrailing: 40,
68+
topTrailing: 20
69+
))
70+
)
71+
}
72+
.padding()
7473
}
75-
.padding()
7674
}

Sources/SwiftUIKit/_Deprecated/DateFormatter+Init.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import Foundation
1010

11-
@available(*, deprecated, message: "This is no longer used within the library and will be removed in the next major release.")
11+
@available(*, deprecated, message: "This is no longer used and will be removed in the next major release.")
1212
public extension DateFormatter {
1313

1414
/**

0 commit comments

Comments
 (0)