微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用@ObservedObject时是否可以在Swift中嵌套属性包装器?

如何解决使用@ObservedObject时是否可以在Swift中嵌套属性包装器?

我最近开始深入研究SwiftUI,Combine和属性包装器的奇妙世界,并且正在努力将@Observedobject与我编写的@Injected属性包装器结合起来,以将依赖项注入到我的视图中。大多数情况下,我的@Injected包装器可以正常工作,但是与@Observedobject配对以管理我的视图模型时,我收到“属性类型与'wrappedValue'属性的类型不匹配”错误。“

这是我@Injected属性包装的当前外观:

@propertyWrapper
public struct Injected<Service> {

    private var service: Service

    public init() {
        self.service = assembler.resolver.resolve(Service.self)!
    }

    public init(name: String? = nil,container: Resolver? = nil) {
        // `assembler` here referring to my global swinject assembler
        self.service = container?.resolve(Service.self,name: name) ??
            assembler.resolver.resolve(Service.self,name: name)!
    }

    public var wrappedValue: Service {
        get {
            return service
        }

        mutating set {
            service = newValue
        }
    }

    public var projectedValue: Injected<Service> {
        get {
            return self
        }

        mutating set {
            self = newValue
        }
    }
}

这是我目前的用法

struct MyModalView: View {
    
    @Observedobject @Injected var viewmodel: MyModalviewmodel
    
    var body: some View {
        Text("Hello World")
    }
}

以这种方式对包装器进行排序,我收到:“属性类型'MyModalviewmodel'与包装类型'Observedobject'的'wrappedValue'属性不匹配”,而MyModalviewmodel类确实从ObservableObject扩展。

如果我翻转包装器,它将编译,但是swinject尝试解析包装的Observedobject类,并且由于容器只是注册原始的MyModalviewmodel类,因此此解析失败并且应用程序崩溃。

同时,通过直接分配来分配@Observedobject值:

@Observedobject var viewmodel: MyModalviewmodel = assembler.resolver.resolve(MyModalviewmodel.self)!

我认为原始代码应该编译,看到@Injected将返回一个符合ObservableObject的包装值,就像@Observedobject期望的一样,尽管所有这些对我来说还是相当陌生的,所以可能我缺少了一些东西。在这里的任何输入将不胜感激。谢谢!

解决方法

对于将来遇到此问题的任何人,我都将两个属性包装器合并在一起,从Resolver项目中借用了实现:

@propertyWrapper
public struct InjectedObject<Service>: DynamicProperty where Service: ObservableObject {
 
    @ObservedObject private var service: Service
    
    public init() {
        self.service = assembler.resolver.resolve(Service.self)!
    }
    
    public init(name: String? = nil,container: Resolver? = nil) {
        self.service = container?.resolve(Service.self,name: name) ??
            assembler.resolver.resolve(Service.self,name: name)!
    }
    
    public var wrappedValue: Service {
        get { return service }
        mutating set { service = newValue }
    }
    
    public var projectedValue: ObservedObject<Service>.Wrapper {
        return self.$service
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。