对于列表-详细信息界面-数据在“详细信息”视图中更新,并且数据已更改但未立即反映在“详细信息”视图中

时间:2019-12-12 01:59:39

标签: ios swiftui

我在Apple Watch上使用SwiftUI,并尝试正确使用@ ObservableObject,@ ObservedObject和@Binding。我正在更新DetailView中的值,并且希望在本地反映它,以及要全局更改数据。下面的代码有效,但是我正在使用kludge强制DetailView重绘自身:

有更好的方法吗?

-------------- ContentView.swift ---------------

import Combine
import SwiftUI

struct person: Identifiable {
    var id:Int = 0
    var name:String
    init( id: Int, name:String) {
        self.id = id
        self.name = name
    }
}

class AppData:  ObservableObject {
    @Published var people:[person] = [person(id:0, name:"John"),
                                      person(id:1, name:"Bret"),
                                      person(id:2,name:"Sue"),
                                      person(id:3,name:"Amy")]
}

var gAppData = AppData()

struct ContentView: View {
    @ObservedObject var model:AppData
    var body: some View {
        List( model.people.indices ){ index in
            NavigationLink(destination: DetailView(person:self.$model.people[index])) { Text(self.model.people[index].name) }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(model:gAppData)
    }
}

-------------- DetailView.swift ---------------

import SwiftUI

struct DetailView: View {
    @Binding var person: person

    // Created an unnecessary var to force a redreaw of the view
    @State var doRedraw:Bool = true

    var body: some View {
        VStack(){
                Text(person.name)
            Button(action:{ self.person.name = "Bob"; self.doRedraw = false }) {
                    Text("Set Name to Bob")
                }
            }

        }
    }

struct DestView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(person:.constant(person( id:0, name:"John"))) // what does ".constant" actually do?
    }
}

1 个答案:

答案 0 :(得分:0)

这里的问题是因为仅当您更改@State@Binding变量时,视图才会重绘。在这里,您无需更改Person变量,但可以更改其属性,该属性不应影响用户界面(因为您没有说要这样做)。我对您的代码做了一些改动,以展示如何实现此效果,您可以从此开始。您需要记住,什么会真正影响用户界面:

class Person: Identifiable, ObservableObject { // better to assign struct/class names using UpperCamelCase

    @Published var name:String // now change of this variable will affect UI
    var id:Int = 0

    init( id: Int, name:String) {
        self.id = id
        self.name = name
    }

}

// changes in DetailView
struct DetailView: View {

    @EnvironmentObject var person: Person

    var body: some View {
        VStack(){
            Text(person.name)
            Button(action:{ self.person.name = "Bob" }) {
                Text("Set Name to Bob")
            }
        }

    }
}

// preview
struct DetailViewWithoutGlobalVar_Previews: PreviewProvider {
    static var previews: some View {
        DetailView()
            .environmentObject(Person(id: 1, name: "John"))
    }
}

更新:“列表和详细信息”的完整代码

import SwiftUI

class Person: Identifiable, ObservableObject { // better to assign type names using UpperCamelCase

    @Published var name: String //{
    var id: Int = 0

    init( id: Int, name:String) {
        self.id = id
        self.name = name
    }

    func changeName(_ newName: String) {
        self.name = newName
    }

}

class AppData: ObservableObject {
    @Published var people: [Person] = [Person(id:0, name:"John"),
                                      Person(id:1, name:"Bret"),
                                      Person(id:2,name:"Sue"),
                                      Person(id:3,name:"Amy")]
}

struct ContentViewWithoutGlobalVar: View {

    @EnvironmentObject var model: AppData

    var body: some View {
        NavigationView { // you forget something to navigate between views
            List(model.people.indices) { index in
                NavigationLink(destination: DetailView()
                    .environmentObject(self.model.people[index])) {
                        PersonRow(person: self.$model.people[index])
                }
            }
        }

    }

}

struct PersonRow: View {

    @Binding var person: Person // this struct will see changes in Person and show them

    var body: some View {
        Text(person.name)
    }

}

struct DetailView: View {

    @EnvironmentObject var person: Person

    var body: some View {
        VStack(){
            Text(self.person.name)
            Button(action:{ self.person.changeName("Bob") }) {
                Text("Set Name to Bob")
            }
        }

    }
}

struct ContentViewWithoutGlobalVar_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentViewWithoutGlobalVar()
                .environmentObject(AppData())

            DetailView()
                .environmentObject(Person(id: 0, name: "John"))
        }
    }
}
相关问题