Есть ли способ отделить виды от моделей вида, как показано ниже? - PullRequest
1 голос
/ 12 апреля 2020

Моя цель - 2 вещи: 1. сделать представление в зависимости от протокола модели представления, а не конкретного класса. 2. вспомогательное представление получает модель представления из среды, а не пропускает ее через иерархию представления. Я упомянул мои цели, поэтому, если есть совершенно другой способ их достижения, я открыт для предложений. Вот что попробовал и потерпел неудачу, конечно, и выдал странную ошибку:

struct ContentView: View {
    var body: some View {
        NavigationView {
            MyView()
        }
    }
}

struct MyView: View {
    @EnvironmentObject var viewModel: some ViewModelProtocol

    var body: some View {
        HStack {
            TextField("Enter something...", text:$viewModel.text)
            Text(viewModel.greetings)
        }
    }
}

//MARK:- View Model
protocol ViewModelProtocol: ObservableObject {
    var greetings: String { get }
    var text: String { get set }
}

class ConcreteViewModel: ViewModelProtocol {
    var greetings: String { "Hello everyone..!" }
    @Published var text = ""
}

//MARK:- Usage
let parent = ContentView().environmentObject(ConcreteViewModel())

Error

1 Ответ

0 голосов
/ 12 апреля 2020

Да, есть, но это не очень красиво.

Вы столкнулись с проблемами, так как компилятор не может понять, как он вообще может определить, какой тип что это some protocol должно быть.

Причина, по которой some работает при объявлении вашего представления, заключается в том, что он выводится из типа того, что вы ему предоставляете.

Если вы сделаете ваше представление структурированным универсальный тип c viewmodel, тогда вы можете получить его и скомпилировать.

struct MyView<ViewModel: ViewModelProtocol>: View {
    @EnvironmentObject var viewModel: ViewModel

    var body: some View {
        Text(viewModel.greetings)
    }
}

Облом здесь, это то, что теперь вы должны объявлять тип viewmodel всякий раз, когда вы используете эта точка зрения, вот так:

let test: MyView<ConcreteViewModel> = MyView()
...