xcode 如何在没有模拟器的情况下预览带绑定的@StateObject

nkoocmlb  于 2023-03-04  发布在  其他
关注(0)|答案(3)|浏览(170)

我正在尝试使用苹果的示例编写一个应用程序,但我意识到Scrumdinger应用程序预览在Xcode预览中不起作用。我启动了一个模拟器,它在那里起作用了。所以我明白这是因为@StateObject。你如何在没有预览的情况下编写代码,或者你如何让它工作?
下面是示例代码:

@main
struct LandLordApp: App {
    @StateObject var store = EstateStore()
    
    var body: some Scene {
        WindowGroup {
            EstatesList(estates: $store.estates)
        }
    }
}

import Foundation

struct Estate: Identifiable, Codable, Hashable {
    var id = UUID()
    var name: String = ""
    var address: String = ""
    var isRented: Bool = false
}

class EstateStore: ObservableObject {
    @Published var estates: [Estate] = []
}

import SwiftUI

struct EstatesList: View {
    
    @Binding var estates: [Estate]
    
    var body: some View {
        NavigationStack {
            List(estates) {estate in
                NavigationLink {
                    Label(estate.name, systemImage: "building.2")
                } label: {
                    Label(estate.name, systemImage: "building.2")
                }
            }
            .toolbar {
                ToolbarItem {
                    Button {
                        estates.append(Estate(name: "Krautzplaz, 10"))
                    } label: {
                        Label("Add", systemImage: "plus")
                    }
                }
            }
        }
    }
}

struct EstatesList_Previews: PreviewProvider {
    
    static var previews: some View {
        EstatesList(estates: .constant(EstateStore().estates))
    }
}

如果你在模拟器中运行,它就可以工作。在预览中,它就不能工作。

5jvtdoz2

5jvtdoz21#

通常我们使用.environmentObject作为数据模型存储对象,如下所示:

@main
struct LandLordApp: App {

// Because this is @StateObject it won't be init during previewing. 
// @StateObject is init before body is called and App's body isn't called when previewing.
    @StateObject var store = EstateStore() 
    
    var body: some Scene {
        WindowGroup {
            EstatesList()
                 .environmentObject(store) // we could also use EstateStore.shared
        }
    }
}
struct EstatesList: View {
    
    @EnvironmentObject var store: EstateStore
    
    var body: some View {
        NavigationStack {
            List($store.estates) { $estate in
struct EstatesList_Previews: PreviewProvider {
    
    static var previews: some View {
        EstatesList()
            .environmentObject(EstateStore(previewing: true)) // or EstateStore.preview
    }
}
class EstateStore: ObservableObject {
    @Published var estates: [Estate] = []

    init(previewing: Bool = false) {
        if previewing {
            estates = [Estate( /* sample data */  )]
        }
    }

    // or singletons if you prefer not to use @StateObject in the App because say you don't want the scene to be recomputed all the time when not using any estate properties.
    //static var shared = EstateStore()
    //static var preview = EstateStore(previewing: true)
}
zfycwa2u

zfycwa2u2#

您可以将@StateObject替换为@ObservedObject,后者具有类似的行为,并且在Xcode预览中受支持。

ou6hu8tu

ou6hu8tu3#

创建类的模拟实现不是预览的典型用例。
在下面的示例中,EstateStore类是一个外部依赖项,由于使用了@StateObject,因此无法直接在预览中使用。

@main
struct LandLordApp: App {
    @StateObject var store = EstateStore()
    
    var body: some Scene {
        WindowGroup {
            EstatesList(store: store)
        }
    }
}

struct EstatesList: View {
    @StateObject var store: EstateStore
    
    var body: some View {
        NavigationStack {
            List(store.estates) {estate in
                NavigationLink {
                    Label(estate.name, systemImage: "building.2")
                } label: {
                    Label(estate.name, systemImage: "building.2")
                }
            }
            .toolbar {
                ToolbarItem {
                    Button {
                        store.estates.append(Estate(name: "Krautzplaz, 10"))
                    } label: {
                        Label("Add", systemImage: "plus")
                    }
                }
            }
        }
    }
}

相关问题