Як сказати погляди SwiftUI, щоб прив'язати до вкладених ObservableObjects


18

У мене є погляд SwiftUI, який займає середовище, що називається appModel. Потім він зчитує значення appModel.submodel.countу своєму bodyметоді. Я очікую , що це зв'язати мій погляд на власність countна submodelтак , що вона повторно робить , коли оновлення властивостей, але це , здається, не буває.

Це помилка? А якщо ні, то який ідіоматичний спосіб, щоб перегляди прив'язувались до вкладених властивостей об'єктів навколишнього середовища у SwiftUI?

Зокрема, моя модель виглядає приблизно так ...

class Submodel: ObservableObject {
  @Published var count = 0
}

class AppModel: ObservableObject {
  @Published var submodel: Submodel = Submodel()
}

І мій погляд виглядає так ...

struct ContentView: View {
  @EnvironmentObject var appModel: AppModel

  var body: some View {
    Text("Count: \(appModel.submodel.count)")
      .onTapGesture {
        self.appModel.submodel.count += 1
      }
  }
}

Коли я запускаю додаток і натискаю на мітку, countвластивість збільшується, але мітка не оновлюється.

Я можу це виправити, перейшовши appModel.submodelяк власність до ContentView, але я хотів би уникати цього, якщо це можливо.


Я також розробляю такий додаток так. У минулому розробці додатків у мене зазвичай є глобальний об’єкт App. Хто-небудь ще думає, що така конструкція класу супер "App" як змінна середовище стане стандартною практикою? Я також розглядав можливість використання декількох EnvironmentObjects, але це важко було підтримати.
Михайло Озерянський

Відповіді:


22

Вкладені моделі ще не працюють у SwiftUI, але ви можете зробити щось подібне

class Submodel: ObservableObject {
    @Published var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()

    var anyCancellable: AnyCancellable? = nil

    init() {
        anyCancellable = submodel.objectWillChange.sink { (_) in
            self.objectWillChange.send()
        }
    } 
}

В основному, ви AppModelловили подію Submodelі надсилаєте її далі до Перегляду

Редагувати:

Якщо вам не потрібно SubModelзайматися класом, ви можете спробувати щось подібне:

struct Submodel{
    var count = 0
}

class AppModel: ObservableObject {
    @Published var submodel: Submodel = Submodel()
}

Дякую, це корисно! Коли ви говорите: "Вкладені моделі ще не працюють у SwiftUI", ви точно знаєте, що вони заплановані?
rjkaplan

Я не впевнений, але, на мою думку, це має спрацювати, я також використовую щось подібне у своєму програмі, тож якщо я знайду кращий підхід, я прийду з редагуванням
Сорін Ліка

@SorinLica Повинен Submodelбути ObservableObject тип?
Farhan Amjad

Це працює! Дивовижне рішення!
Md Shahed Hossain

1

Усі три ViewModels можуть спілкуватися та оновлюватись

// First ViewModel
class FirstViewModel: ObservableObject {
var facadeViewModel: FacadeViewModels

facadeViewModel.firstViewModelUpdateSecondViewModel()
}

// Second ViewModel
class SecondViewModel: ObservableObject {

}

// FacadeViewModels Combine Both 

import Combine // so you can update thru nested Observable Objects

class FacadeViewModels: ObservableObject { 
lazy var firstViewModel: FirstViewModel = FirstViewModel(facadeViewModel: self)
  @Published var secondViewModel = secondViewModel()
}

var anyCancellable = Set<AnyCancellable>()

init() {
firstViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)

secondViewModel.objectWillChange.sink {
            self.objectWillChange.send()
        }.store(in: &anyCancellable)
}

func firstViewModelUpdateSecondViewModel() {
     //Change something on secondViewModel
secondViewModel
}

Дякую Соріну за рішення Комбінат.


Чи можете ви оновити код? у ньому багато помилок компілятора
DevB2F

-2

Це схоже на помилку. Коли я оновлюю xcode до останньої версії, він працює правильно при прив’язці до вкладених ObservableObjects


Чи можете ви уточнити, на якій версії xcode ви зараз працюєте? Наразі у мене є Xcode 11.0 і я відчуваю це питання. У мене виникли проблеми з оновленням до 11.1, воно не пройде, як на 80%.
Михайло Озерянський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.