Возможно ли вложить оболочки свойств в Swift при использовании @ObservedObject?

#swift #swiftui #combine #property-wrapper

#swift #swiftui #объединить #свойство-оболочка

Вопрос:

Недавно я начал углубляться в удивительный мир оболочек SwiftUI, Combine и property и изо всех сил пытаюсь объединить @ObservedObject с оболочкой @Injected property, которую я написал, чтобы внедрить зависимости в мои представления. Большую часть времени моя оболочка @Injected работает нормально, но при сопряжении с @ObservedObject для управления моими viewmodels я получал «Тип свойства не соответствует типу свойства wrappedValue» ошибки».

Вот как выглядит моя оболочка @Injected property:

 @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’ не совпадает с типом свойства’wrappedValue’ его типа оболочки’ObservedObject'», в то время как класс MyModalViewModel распространяется на ObservableObject.

Если я переворачиваю обертки, он компилируется, но Swinject пытается разрешить обернутый класс ObservedObject, и поскольку контейнер просто регистрирует исходный класс MyModalViewModel, это разрешение не выполняется, и приложение вылетает.

Между тем, присвоение значения @ObservedObject посредством прямого присваивания работает:

 @ObservedObject var viewModel: MyModalViewModel = assembler.resolver.resolve(MyModalViewModel.self)!
  

Я бы подумал, что исходный код должен быть скомпилирован, поскольку @Injected вернет обернутое значение, соответствующее ObservableObject , как ожидает @ObservedObject , хотя все это все еще довольно ново для меня, поэтому, возможно, я что-то упускаю. Любой ввод здесь был бы весьма признателен. Спасибо!!

Комментарии:

1. @ObservedObject @Injected — такая комбинация сейчас не поддерживается swift

2. Существует библиотека внедрения зависимостей под названием Resolver . У них есть @InjectedObject оболочка свойств. Который сочетает @ObservedObject @Injected в себе и. Может быть, вы можете взглянуть на

3. @the.blaggy О, snap, я слышал об этом, но понятия не имел, что у них есть встроенная поддержка ObservedObject! В таком случае я сам отвечу на свой вопрос.

Ответ №1:

Для тех, кто столкнется с этим в будущем, я решил объединить две оболочки свойств под одной крышей, позаимствовав реализацию из проекта 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
    }
}
  

Ответ №2:

Используйте аннотацию @InjectedObject или Service locator из Resolver. И не забудьте зарегистрировать свой инициализатор.

Учебное пособие здесь