Могу ли я создать общий класс ObservableObject, который может использоваться несколькими ContentViews? - PullRequest
0 голосов
/ 24 сентября 2019

Привет, мне просто интересно, возможно ли создать общий класс, подтверждающий протокол ObservableObject, который может использоваться более чем одним ContentViews.

Если я смогу это сделать, тогда я смогу сделать мой ContentView иКласс модели полностью универсальный и многократно используемый.

Пример того, чего я хотел бы достичь:

protocol ContentViewModelType: ObservableObject {
    var propertyToInitialiseView: [String] { get }
}

struct ContentView: View {
    @ObservedObject var viewModel: some ViewModel

    var body: some View {
        Text("Hello World")
    }
}

Если я смогу это сделать, любой класс сможет реализовать ContentViewModelType и стать моделью для ContentView, которая делаетэто универсальный и многоразовый.Например,

class ViewModel: ObservableObject {
    var objectWillChange = PassthroughSubject<ViewModel, Never>()
}

Но когда я пытаюсь инициализировать ContentView, этот xcode выдает ошибку типа.

enter image description here

Я думал, чтоВесь смысл введения некоторого ключевого слова заключался в том, чтобы мы могли использовать протокол в качестве типа для тех протоколов, которые связали тип в качестве требования, и, следовательно, это должно работать.Но это дает ошибку.

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

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 24 сентября 2019

Это не то, для чего some.some создает непрозрачный тип возвращаемого значения, а не экзистенциальный («любой») тип. Подробнее см. В документах. См. Также Что такое ключевое слово some в SwiftUI? 1006 *

Тип some должен быть одного типа, известного ввремя компиляции.Это просто не известно звонящему.То, что вы пытаетесь сделать, это передать экзистенциальный тип, известный в runtime .Ничего не изменилось в Swift 5.1 по поводу существования.Вы все равно должны были бы обернуть это в AnyContentViewModel, если это то, что вы хотели.(Мне нужно немного подумать о том, будет ли это хорошей идеей или нет.)

Но код, который вы написали, также не выполняет то, что вы описываете.Вы на самом деле нигде не используете ContentViewModelType.Вы имели в виду some ContentViewModelType?Это все еще не сработает, но, похоже, ты имеешь в виду.

0 голосов
/ 27 сентября 2019

Если я правильно вас понимаю, вы можете сделать что-то вроде этого:

У вас может быть класс ObservableObject следующим образом:

import Foundation

class SampleTimer: ObservableObject {
    @Published var timerVar: Int = 0

    init(){
        Timer.scheduledTimer(withTimeInterval: 1, repeats: true){
            timer in
            DispatchQueue.main.async {
                self.timerVar += 1
            }
        }
    }
}

a ContentView:

import SwiftUI

struct ContentView: View {
    @ObservedObject var sampleTimer = SampleTimer()
    var body: some View {
        NavigationView {
            VStack {
                Text("\(sampleTimer.timerVar)")
                NavigationLink(destination: SecondView(sampleTimer: sampleTimer) ){
                    Text("Go to second view")
                }
            }
        }
    }
}

и SecondView вроде:

import SwiftUI

struct SecondView: View {
    @ObservedObject var sampleTimer : SampleTimer
    var body: some View {
        VStack {
            Text("\(sampleTimer.timerVar)")
        }
    }
}

Важно отметить, что если у вас есть таймер, как у меня, и он инициализируется в функции init() И вы создаете новыйэкземпляр SampleTimer() в SecondView (то есть @ObservedObject var sampleTimer = SampleTimer() вместо того, что у меня есть) вместо передачи одного экземпляра из ContentView() в SecondView() у вас будет два разных экземпляра SampleTimer, означающихчто значения не будут одинаковыми в ContentView и SecondView

...