bpi*_*ano 2 swift swiftui swiftui-environment
我正在使用 WWDC 2023 上推出的带有 SwiftUI 的最新观察框架。似乎新的@Environment属性包装器不允许使用协议。我的服务实现如下所示:
protocol UserServiceRepresentation {
var user: User { get }
}
// Service implementation
@Observable
final class UserService: UserServiceRepresentable {
private(set) var user: User
func fetchUser() async { ... }
}
// Service mock
@Observable
final class UserServiceMock: UserServiceRepresentable {
let user: User = .mock
}
Run Code Online (Sandbox Code Playgroud)
以前,可以使用@EnvironmentObject声明协议,以便您可以将模拟服务作为环境对象传递给视图。
struct UserView: View {
// This is possible using EnvironmentObject.
// But it require UserService to conforms to ObservableObject.
@EnvironmentObject private var userService: UserService
var body: some View { ... }
}
#Preview {
UserView()
.environmentObject(UserServiceMock()) // this allows your previews not to rely on production data.
}
Run Code Online (Sandbox Code Playgroud)
现在,对于@Environment,我不能做这样的事情:
struct UserView: View {
// This is not possible
// Throw compiler error: No exact matches in call to initializer
@Environment(UserService.self) private var userService
var body: some View { ... }
}
Run Code Online (Sandbox Code Playgroud)
我很乐意像这样注入我的模拟用户服务:
#Preview {
UserView()
.environment(UserServiceMock())
}
Run Code Online (Sandbox Code Playgroud)
我是否错过了什么或以错误的方式做事?新的属性包装器似乎@Environment不是为这种用途而构建的。我在网上找不到任何有关它的信息。在此先感谢您的帮助。
不,@Environment初始化器采用具体类型,即,并且继续使用和Observable没有任何问题。如果它没有坏,就不要修理它。EnvironmentObjectObservableObject
如果出于某种原因您确实喜欢@Observable,您可以创建一个存储用户服务的自定义环境密钥。环境键的值可以是存在协议类型。
struct UserServiceKey: EnvironmentKey {
// you can also set the real user service as the default value
static let defaultValue: any UserServiceRepresentation = UserServiceMock()
}
extension EnvironmentValues {
var userService: any UserServiceRepresentation {
get { self[UserServiceKey.self] }
set { self[UserServiceKey.self] = newValue }
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以调用Environment采用键路径的初始化程序。
@Environment(\.userService) var service
Run Code Online (Sandbox Code Playgroud)
.environment(\.userService, someService)
Run Code Online (Sandbox Code Playgroud)
请注意,如果 的实例UserServiceRepresentation不是Observable,则此操作将不起作用。要求Observable一致性可能会更好。
protocol UserServiceRepresentation: Observable
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
388 次 |
| 最近记录: |