Skip to content

Commit 5854aec

Browse files
committed
Add AsyncPreview package
1 parent efcd60e commit 5854aec

File tree

4 files changed

+90
-1
lines changed

4 files changed

+90
-1
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

Package.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// swift-tools-version: 5.9
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "AsyncPreview",
8+
platforms: [
9+
.macOS(.v14), .iOS(.v13), .tvOS(.v13), .visionOS(.v1)
10+
],
11+
products: [
12+
// Products define the executables and libraries a package produces, making them visible to other packages.
13+
.library(
14+
name: "AsyncPreview",
15+
targets: ["AsyncPreview"]),
16+
],
17+
targets: [
18+
// Targets are the basic building blocks of a package, defining a module or a test suite.
19+
// Targets can depend on other targets in this package and products from dependencies.
20+
.target(
21+
name: "AsyncPreview",
22+
exclude: ["README.md", "LICENSE"]),
23+
]
24+
)

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
11
# AsyncPreview
2-
Preview asynchronous views on Xcode canvas.
2+
3+
Preview views with asynchronous dependencies, on Xcode canvas.
4+
5+
## Usage
6+
7+
```
8+
#Preview {
9+
AsyncModel { model in
10+
SomeView().environment(model)
11+
} model: {
12+
try await SomeAsynchronousModel()
13+
}
14+
}
15+
```
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// AsyncPreview.swift
3+
// Circuit
4+
//
5+
// Created by Alt on 2024-03-09.
6+
//
7+
8+
import Foundation
9+
import SwiftUI
10+
11+
struct AsyncPreview<V: View, M>: View {
12+
13+
var view: (M) -> V
14+
var model: () async throws -> M?
15+
16+
@State internal var internalModel: M?
17+
@State internal var error: Error?
18+
19+
var body: some View {
20+
internalBody
21+
.task {
22+
do {
23+
self.internalModel = try await model()
24+
} catch {
25+
self.error = error
26+
print(error)
27+
}
28+
}
29+
}
30+
31+
@ViewBuilder
32+
internal var internalBody: some View {
33+
if let internalModel {
34+
view(internalModel)
35+
}
36+
else if let error {
37+
Label(error.localizedDescription, systemImage: "exclamationmark.triangle.fill")
38+
}
39+
else {
40+
// Note: We need an actual view to trigger the `task` in `body`
41+
ProgressView().progressViewStyle(.circular)
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)