วิธีบอกมุมมอง SwiftUI เพื่อผูกกับ ObservableObjects ที่ซ้อนกัน


18

ผมมีมุมมองที่ SwiftUI ที่ใช้เวลาใน EnvironmentObject 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แต่ฉันต้องการหลีกเลี่ยงถ้าเป็นไปได้


ฉันยังออกแบบแอพของฉันเช่นนี้ ฉันมักจะมีวัตถุทั่วโลกในการพัฒนาแอปที่ผ่านมา มีใครอีกบ้างที่คิดว่าการออกแบบคลาส "แอพ" สุดยอดนี้เนื่องจากตัวแปรสภาพแวดล้อมจะกลายเป็นแนวปฏิบัติมาตรฐานหรือไม่ ฉันก็กำลังพิจารณาใช้ EnvironmentObjects หลายอัน แต่มันก็ยากที่จะรักษา
Michael Ozeryansky

คำตอบ:


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

ฉันไม่แน่ใจ แต่ในความคิดของฉันมันควรจะทำงานฉันยังใช้สิ่งที่คล้ายกันใน proj ของฉันดังนั้นถ้าฉันจะหาวิธีที่ดีกว่าฉันจะมาพร้อมกับการแก้ไข
โซริน Lica

@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%
Michael Ozeryansky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.