这是一个简单的包,它提供了一个围绕 AsyncStream 的便捷属性包装器,其行为几乎与 @Published
完全相同。
Package Dependencies
(软件包依赖项)Add Package
(添加软件包)在您的 Package.swift
文件中,添加以下内容
let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://github.com/BrentMifsud/AsyncValue.git", from: .init(1, 0, 0))
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "MyPackage",
targets: ["MyPackage"]
),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "MyPackage",
dependencies: ["AsyncValue"]
),
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"]
),
]
)
@AsyncValue var myValue: String = "Test"
print(myValue) // prints: test
就像支持 @Published
的 publisher 一样,AsyncValue
由 AsyncStream 支持。 您可以订阅值的更新。
@AsyncValue myValue: String = "Test"
Task {
for await value in myValue {
print("Value: \(value)")
}
}
Task {
await Task.sleep(nanoseconds: 1_000_000_000)
myValue = "New Value"
}
/* Prints:
Value: test
Value: New Value
*/
AsyncStream 的一个主要限制是,您只能使用单个任务对其进行 for-await-in
操作。
AsyncValue
没有此限制
@AsyncValue myValue: String = "Test"
Task {
for await value in myValue {
print("Task 1 Value: \(value)")
}
}
Task {
for await value in myValue {
print("Task 2 Value: \(value)")
}
}
Task {
await Task.sleep(nanoseconds: 1_000_000_000)
myValue = "New Value"
}
/* Prints (note that the order of the tasks printing may vary as this is happening asyncronously):
Task 1 Value: test
Task 2 Value: test
Task 2 Value: New Value
Task 1 Value: New Value
*/
只需一行代码,即可调整 AsyncValue
以与 ObservableObject
无缝协作
class MyObservableObject: ObservableObject {
@AsyncValue var myValue: String = "Test"
}
对 AsyncValue
的任何更改都将以与 @Published
相同的方式触发视图更新。
感谢 jlsiewert 提出了这个很酷的技巧,使它可以自动工作。
还有一个 .onRecieve(sequence:perform:)
视图修饰符,允许您响应来自任何 AsyncSequence 的更改。
struct MyView: View {
var body: some View {
Text("Hello World!")
.onReceive(myService.$myValue) { value in
print("The value changed to: \(value)")
}
}
}
class MyService: ObservableObject {
@AsyncValue var myValue: String = "Test"
}