SwiftUI: использование @Binding с переменной @Property из протокола - PullRequest
0 голосов
/ 30 марта 2020

У меня есть ParentView, из которого я хочу передать переменную @Published в Subview, где она будет использоваться как @ Bindable.

Это работает при использовании MyViewModel следующим образом:

class MyViewModel: ObservableObject {
    @Published var soundOn = true
}

struct ParentView: View {
    @ObservedObject var myViewModel: MyViewModel
    var body: some View {
        Subview(soundOn: $myViewModel.soundOn)
    }
}

struct Subview: View {
    @Binding var soundOn: Bool
    var body: some View {
        Image(soundOn ? "soundOn" : "soundOff")
    }
}

но я хочу повторно использовать Subview для всех ViewModels, соответствующих протоколу HasSoundOnOff. При использовании протокола HasSoundOnOff я не могу определить @Published внутри протокола, а это означает, что ParentView видит только обычную переменную non-@Published и не может использовать $ viewModel.soundOn.

protocol HasSoundOnOff {
    var soundOn: Bool { get set }
}

class MyViewModel: HasSoundOnOff {
    @Published var soundOn = true
}

struct ParentView<ViewModel: ObservableObject & HasSoundOnOff>: View {
    @ObservedObject var viewModel: ViewModel
    var body: some View {
        Subview(soundOn: $viewModel.soundOn) //<----- error: "Expression type 'Binding<_>' is ambiguous without more context" because protocols can't have @Published and therefor soundOn is treated like a non-@Published variable
    }
}

Я могу разрешить MyViewModel наследовать от класса, который определяет переменную @Published, поэтому работает следующий код:

class InheritFromPublishedVarClass: ObservableObject {
    @Published var soundOn = true
}

class MyViewModel: ObservableObject & InheritFromPublishedVarClass {}

struct ParentView<ViewModel: ObservableObject & InheritFromPublishedVarClass>: View {
    @ObservedObject var viewModel: ViewModel
    var body: some View {

        Subview(soundOn: $viewModel.soundOn)
    }
}

Это означает, что я могу повторно использовать мою переменную @Published, но это не будет масштабироваться, поскольку множественное наследование не разрешено.

Это серьезно ограничивает возможность повторного использования кода для меня. Должен быть способ добиться этого более масштабируемым образом. Любые идеи? Требуется, чтобы ParentView принимал параметр Generi c ViewModel.

1 Ответ

0 голосов
/ 30 марта 2020

Не могли бы вы использовать

@EnvironmentObject var myViewModel: MyViewModel

в ваших представлениях, где вам нужен доступ к нему. Затем используйте его как

myViewModel.soundOn 

, вам не нужно будет передавать его через Представления как Привязки, поскольку у вас будет доступ к soundOn в любом представлении, в котором вы объявите свой объект @EnvironmentObject.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...