You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+252-6Lines changed: 252 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,22 +6,268 @@ ViewStateController is a framework for Swift and SwiftUI developers that provide
6
6
7
7
There is an Example app available [here](https://github.com/mdb1/ViewStateControllerExampleApp), where most of the configuration options can be tweaked.
8
8
9
-
// TODO: Upload a Video of the Example App
10
-
11
9
# ViewStateController Object
12
10
13
-
# WithViewState Modifier
11
+
The ViewStateController struct is the one that contains the array of historical [ViewStates](https://mdb1.github.io/2023-01-08-new-app-view-state/) and has computed properties that will be used by the ViewStateModifier to determine what to do.
12
+
13
+
*`isInitialLoading`: Returns true only if loading state was set once and there hasn't been errors or info yet.
14
+
*`isLoading`: Returns true if state is loading.
15
+
*`latestValidInfo`: Info associated to the last time `loaded` state was set. Nil if there has been an error after the latest info.
16
+
*`latestInfo`: Info associated to the last time `loaded` state was set, disregarding if there has been an error afterwards.
17
+
*`latestValidError`: Info associated to the last time `error` state was set. Nil if `info` has been loaded after the latest error.
18
+
*`latestError`: Info associated to the last time loaded `error` was set, disregarding if there has been an error afterwards.
19
+
*`latestNonLoading`: Returns the latest informational state (info, or error) if exists. Nil otherwise.
20
+
21
+
There are also two mutating methods:
22
+
23
+
*`setState(_ state: ViewState<Info>)`: Sets the new state into the states array.
24
+
*`reset()`: Resets everything.
25
+
26
+
# ViewStateModifier
27
+
28
+
The ViewStateModifier is a ViewModifier that uses the given ViewStateController and configurable options to automatically update the state of a view.
29
+
30
+
The code of the modifier is pretty straight forward:
31
+
```swift
32
+
funcbody(content: Content) ->some View {
33
+
if controller.isInitialLoading {
34
+
// Initial loading modifier displayed on the initial loading state.
35
+
content.modifier(initialLoadingModifier)
36
+
} elseiflet info = controller.latestValidInfo {
37
+
// If we have valid info loaded we display it:
38
+
loadedView(info)
39
+
.if(controller.isLoading) { view in
40
+
// If we are on a subsequent loading, we add the modifier.
41
+
view.modifier(loadingAfterInfoModifier)
42
+
}
43
+
} elseiflet error = controller.latestValidError {
44
+
// If we have a value error we display it:
45
+
errorView(error)
46
+
.if(controller.isLoading) { view in
47
+
// If we are on a subsequent loading, we add the modifier.
48
+
view.modifier(loadingAfterErrorModifier)
49
+
}
50
+
} else {
51
+
// Otherwise, we display the initial content.
52
+
content
53
+
}
54
+
}
55
+
```
56
+
57
+
The method `withViewStateModifier`, is just a convenience way to add the ViewStateModifier to any view:
58
+
59
+
```swift
60
+
/// Adds a view state modifier that can display different views depending on the state of a `ViewStateController`.
61
+
/// - Parameters:
62
+
/// - controller: The `ViewStateController` that controls the state of the view.
63
+
/// - indicatorView: The view to show when the view is loading.
64
+
/// - initialLoadingType: The type of loading indicator to show when the view is initially loading.
65
+
/// - loadedView: The view to show when the view is not loading and has valid information.
66
+
/// - loadingAfterInfoType: The type of loading indicator to show when the view is loading after it has already
67
+
/// displayed valid information.
68
+
/// - errorView: The view to show when the view has an error.
69
+
/// - loadingAfterErrorType: The type of loading indicator to show when the view is loading after it has displayed
1. Decide your strategy for `initialLoading`, `loadingAfterInfo`, `errorView`, and `loadingAfterError` states.
87
+
2. Create the placeholder view (The one that will be there before the initial loading). (This could be an `EmptyView()` or the `loadedView` with a `.redacted` modifier).
88
+
3. Create the `loadedView`.
89
+
4. Decide if the error state will have a retry action or not.
14
90
15
91
## Examples with code samples
16
92
17
-
TODO: Upload videos here
93
+
Let's take a look at how we can use it in our views:
94
+
95
+
We will be using this view and controller in our examples:
Since we are not changing the values for the loading types it's using the default values:
143
+
144
+
*`.material()` for the initial loading
145
+
*`.horizontal()` for the loading after info type
146
+
*`.overCurrentContent(alignment: .trailing)` for the loading after error type
147
+
148
+
### Changing the indicator view
149
+
150
+
If you have a custom progress view, you can use it in the `indicatorView` parameter. Example from [this post](https://mdb1.github.io/2023-01-04-new-app-components/):
By changing the `initialLoadingType`, `loadingAfterInfoType`, or `loadingAfterErrorType` you can provide different ways of displaying the loading states.
170
+
171
+
You can find a list of the possible options [here](https://github.com/mdb1/ViewStateController/blob/main/Sources/ViewStateController/ViewModifiers/LoadingViewModifier.swift)
loadingAfterErrorType: .overCurrentContent(contentOpacity: 0.5, alignment: .bottomTrailing) // Mark 4
187
+
)
188
+
```
189
+
190
+
In this example:
191
+
192
+
* Mark 1: We are changing the indicator view to use a custom one.
193
+
* Mark 2: We are changing the initial loading type, to use a VStack with the indicator at the bottom and center alignment.
194
+
* Mark 3: We are changing the loading after info type, to use an HStack with the indicator in the leading position, 0.3 as the opacity for the content, center alignment, and 32 of spacing.
195
+
* Mark 4: We are changing the loading after error type to use the `overCurrentContent` type with 0.5 for the content opacity, and bottomTrailing alignment.
In this video, we are tweaking around some properties and pass them to the `withViewStateModifier` to demonstrate the different loading and error states that comes for free. Everything is configurable, and there is also the ability to provide custom views for loading states, the indicator, and the error states.
261
+
262
+
The app used for this video can be downloaded from [this repository](https://github.com/mdb1/ViewStateControllerExampleApp).
0 commit comments