#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
— такая комбинация сейчас не поддерживается swift2. Существует библиотека внедрения зависимостей под названием 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. И не забудьте зарегистрировать свой инициализатор.