Swiftui - ฉันจะเริ่มต้น Obbject ที่สังเกตได้โดยใช้ environmentobject เป็นพารามิเตอร์ได้อย่างไร


9

ฉันไม่แน่ใจว่านี่เป็นปฏิปักษ์ในโลก SwiftUI ใหม่ที่กล้าหาญที่เราอาศัยอยู่ แต่โดยพื้นฐานแล้วฉันมี @EnvironmentObject พร้อมกับข้อมูลผู้ใช้พื้นฐานบางอย่างที่บันทึกไว้ในมุมมองของฉันที่สามารถโทรได้

ฉันยังมี @ObservedObject ซึ่งเป็นเจ้าของข้อมูลบางอย่างที่จำเป็นสำหรับมุมมองนี้

เมื่อมุมมองปรากฏขึ้นฉันต้องการใช้ @EnvironmentObject เพื่อเริ่มต้น @ObservedObject:

struct MyCoolView: View { 

    @EnvironmentObject userData: UserData
    @ObservedObject var viewObject: ViewObject = ViewObject(id: self.userData.UID)  

    var body: some View { 
            Text("\(self.viewObject.myCoolProperty)")
    } 
}

น่าเสียดายที่ฉันไม่สามารถเรียกตนเองว่าตัวแปรสภาพแวดล้อมจนกว่าจะเริ่มต้น:

"ไม่สามารถใช้สมาชิกอินสแตนซ์ 'userData' ภายในคุณสมบัติตัวเริ่มต้นคุณสมบัติตัวเริ่มต้นคุณสมบัติที่เรียกใช้ก่อนที่ 'ตัวเอง' จะพร้อมใช้งาน"

ฉันเห็นเส้นทางที่เป็นไปได้สองสามทาง แต่พวกเขาทั้งหมดรู้สึกเหมือนแฮ็ก ฉันจะเข้าใกล้สิ่งนี้ได้อย่างไร


บางทีคุณสามารถลองเพิ่มแบบกำหนดเองinitลงในโครงสร้างได้
nayem

ฉันลองและได้รับข้อผิดพลาดที่ค่อนข้างแปลก: Property wrappers are not yet supported on local properties โดยทั่วไปแล้วมันบอกว่าฉันไม่สามารถสร้าง @ObservedObject ในวิธีการเริ่มต้น
snarik

คำตอบ:


9

นี่คือวิธีการ (IMO ที่ง่ายที่สุด):

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        MyCoolInternalView(ViewObject(id: self.userData.UID))
    }
}

struct MyCoolInternalView: View {
    @EnvironmentObject var userData: UserData
    @ObservedObject var viewObject: ViewObject

    init(_ viewObject: ViewObject) {
        self.viewObject = viewObject
    }

    var body: some View {
            Text("\(self.viewObject.myCoolProperty)")
    }
}

มันสมบูรณ์แบบ MyCoolView เป็นเด็กในมุมมอง 'บ้าน' ที่ฉันประกาศ ObservedObject ขอบคุณ!
snarik

แต่ถ้าคุณต้องการจัดการ userData ภายใน ViewObject โดยไม่ต้องสร้าง ViewObject ใหม่ทุกครั้ง?
BobiSad

0

แทนที่จะสร้างมุมมองย่อยคุณสามารถเพิ่ม dummy initializer ให้กับคุณ"ViewObject"เพื่อให้คุณสามารถเรียกมันก่อนที่จะเรียก initializer จริง

struct MyCoolView: View { 

    @EnvironmentObject userData: UserData
    @ObservedObject var viewObject: ViewObject

    init() {
        viewObject = ViewObject()
        defer {
            viewObject = ViewObject(id: self.userData.UID)
        }
    }

    var body: some View { 
            Text("\(self.viewObject.myCoolProperty)")
    } 
}

สำหรับบันทึกที่ฉันยังไม่ได้ทดสอบ


0

นี่เป็นวิธีที่ง่ายไป:

struct MyCoolView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Observe(obj: ViewObject(id: userData.UID)) { viewObject in
             Text("\(viewObject.myCoolProperty)")
        }
    }
}

ด้วยผู้ช่วยตัวนี้ที่ทำให้มันทำงานได้:

struct Observe<T: ObservableObject, V: View>: View {
    @ObservedObject var obj: T
    let content: (T) -> V
    var body: some View { content(obj) }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.