Как деинсталлировать ViewModel с каркасом объединения, когда представления исчезают - PullRequest
0 голосов
/ 17 марта 2020

Я использую Combine в viewModels для обновления представлений. Но если я сохраню объекты AnyCancellable в наборе AnyCancellable, метод deinit никогда не вызывается. Я использую deinit для отмены всех отменяемых объектов.

struct View1: View {

    @ObservedObject var viewModel:ViewTextModel = ViewTextModel()
    @Injected var appActions:AppActions

    var body: some View {
        VStack {
            Text(self.viewModel.viewText)

            Button(action: {
                self.appActions.goToView2()
            }) {
                Text("Go to view \(self.viewModel.viewText)")
            }
        }
    }
}
class ViewTextModel: ObservableObject {
    @Published var viewText: String

    private var cancellables = Set<AnyCancellable>()

    init(state:AppState) {
        // initial state
        viewText = "view  \(state.view)"
        // updated state
        state.$view.removeDuplicates().map{ "view \($0)"}.assign(to: \.viewText, on: self).store(in: &cancellables)
    }

    deinit {
        cancellables.forEach { $0.cancel() }
    } 
}

Каждый раз, когда перестраивается представление, создается новая модель представления, но старая не уничтожается. Атрибут viewText обновляется в каждом экземпляре с state.$view.removeDuplicates().map{ "view \($0)"}.assign(to: \.viewText, on: self).store(in: &cancellables)

Если я не сохраняю отменяемый объект в наборе, вызывается deinit, но viewText не обновляется, если состояние изменилось для текущий вид.

Есть ли у вас представление о том, как управлять обновлением состояния без умножения экземпляров модели представления?

Спасибо

1 Ответ

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

Вы могли бы использовать sink вместо assign:

state.$view
    .removeDuplicates()
    .sink { [weak self] in self?.viewText = $0 }
    .store(in: &cancellables)

Но я вообще сомневаюсь в необходимости объединения. Просто используйте вычисляемое свойство:

class ViewTextModel: ObservableObject {
    @Published var state: AppState

    var viewText: String { "view \(state.view)" }
}
...