首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI AppStorage,UserDefaults和ObservableObject

SwiftUI AppStorage,UserDefaults和ObservableObject
EN

Stack Overflow用户
提问于 2021-03-29 02:27:37
回答 2查看 1.8K关注 0票数 2

我有两个不同的观点,ContentView和CreateView。在CreateView中,我通过textfield获取用户的输入,一旦用户单击Save按钮,输入将存储在AppStorage中。然后,我想在ContentView上显示保存的输入。在这里,我尝试使用State & Binding,但效果不太好。如何在CreateView中使用在ContentView中创建的变量?我应该使用什么财产..。

谢谢

这是最新的问题和代码..。

代码语言:javascript
复制
struct ContentView: View {
    // MARK: - PROPERTY
    @ObservedObject var appData: AppData
    let createpage = CreatePage(appData: AppData())
    
    var body: some View {
        HStack {
            NavigationLink("+ create a shortcut", destination: CreatePage(appData: AppData()))
                .padding()
            Spacer()
        } //: HStack - link to creat page
        VStack {
            Text("\(appData.shortcutTitle) - \(appData.shortcutOption)")
        }
        
    }
    
    struct CreatePage: View {
        // MARK: - PROPERTY
        @AppStorage("title") var currentShortcutTitle: String?
        @AppStorage("option") var currentOption: String?
        @Environment(\.presentationMode) var presentationMode
        @ObservedObject var appData: AppData
        
        var body: some View {
            NavigationView{
                ScrollView{
                    Text("Create a ShortCut")
                        .padding()
                    
                    HStack {
                        TextField("what is the title?", text: $appData.titleInput)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            //.frame(width: 150, height: 60, alignment: .center)
                            .border(Color.black)
                            .padding()
                    } //: HStack - Textfield - title
                    .padding()
                    
                    HStack (spacing: 10) {
                        TextField("options?", text: $appData.optionInput)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            .frame(width: 80, height: 40, alignment: .leading)
                            .padding()
                    } //: HStack - Textfield - option
                    .padding()
                    
                    Button(action: {
                        self.appData.shortcutTitle = self.appData.titleInput
                        self.appData.shortcutOption = self.appData.optionInput
                        UserDefaults.standard.set(appData.shortcutTitle, forKey: "title")
                        UserDefaults.standard.set(appData.shortcutOption, forKey: "option")
                        presentationMode.wrappedValue.dismiss()
                    }, label: {
                        Text("Save")
                            .padding()
                            .frame(width: 120, height: 80)
                            .border(Color.black)
                    }) //: Button - save
                    .padding(.top, 150)
                } //: Scroll View
            } //: Navigation View
        } //: Body
        
        class AppData: ObservableObject {
            @Published var shortcutTitle : String = "Deafult Shortcut"
            @Published var shortcutOption : String = "Default Option"
            @Published var titleInput : String = ""
            @Published var optionInput : String = ""
        }

所以问题是

当我在

  1. 上放置新输入并在CreatePage按钮上设置选项时,新输入不会出现在ContentView page.The output上,它会继续显示标题和选项的默认值,而不会显示用户输入。如果用户输入了新的输入并点击了保存按钮,我希望将它们存储在AppStorage中,并希望将数据保存在ContentView上(还没有创建UI )。我在正确的方向上使用AppStorage和UserDefaults吗?

如果有人对这些问题有洞察力..。愿意接受你的建议或推荐信。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-29 05:25:03

您正在多个地方创建AppData实例。为了共享数据,您必须共享AppData的一个实例。

我假定您在ContentView的父视图中创建了@ObservedObject var appData: AppData,因为您在视图的顶部定义了@ObservedObject var appData: AppData(没有= AppData())。这可能在您的WindowGroup中,您还必须有一个NavigationView

我删除了next (let createpage = CreatePage(appData: AppData())),因为它什么也不做。在NavigationLink中,我传递了相同的AppData实例。

代码语言:javascript
复制
struct ContentView: View {
    // MARK: - PROPERTY
    @StateObject var appData: AppData = AppData() //Don't need to have `= AppData()` if you already create it in a parent view
    
    var body: some View {
        // I'm assuming there's a NavigationView in a parent view
        VStack { //note that I've wrapped the whole view in a VStack to avoid having two root nodes (which can perform differently in NavigationView depending on the platform)
            HStack {
                NavigationLink("+ create a shortcut", destination: CreatePage(appData: appData))
                    .padding()
                Spacer()
            } //: HStack - link to creat page
            VStack {
                Text("\(appData.shortcutTitle) - \(appData.shortcutOption)")
            }
        }
    }
}

struct CreatePage: View {
    // MARK: - PROPERTY
    @AppStorage("title") var currentShortcutTitle: String?
    @AppStorage("option") var currentOption: String?
    @Environment(\.presentationMode) var presentationMode
    @ObservedObject var appData: AppData
    
    var body: some View {
        NavigationView{
            ScrollView{
                Text("Create a ShortCut")
                    .padding()
                
                HStack {
                    TextField("what is the title?", text: $appData.titleInput)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        //.frame(width: 150, height: 60, alignment: .center)
                        .border(Color.black)
                        .padding()
                } //: HStack - Textfield - title
                .padding()
                
                HStack (spacing: 10) {
                    TextField("options?", text: $appData.optionInput)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                        .frame(width: 80, height: 40, alignment: .leading)
                        .padding()
                } //: HStack - Textfield - option
                .padding()
                
                Button(action: {
                    appData.shortcutTitle = appData.titleInput
                    appData.shortcutOption = appData.optionInput
                    presentationMode.wrappedValue.dismiss()
                }, label: {
                    Text("Save")
                        .padding()
                        .frame(width: 120, height: 80)
                        .border(Color.black)
                }) //: Button - save
                .padding(.top, 150)
            } //: Scroll View
        } //: Navigation View
    } //: Body
}

关于@AppStorageUserDefaults,现在很难用它们来判断您的意图。但是,您不需要声明AppStorage并以相同的键调用UserDefaults -- @AppStorage为您写UserDefaults。在https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-appstorage-property-wrapper阅读更多内容

票数 2
EN

Stack Overflow用户

发布于 2021-03-29 13:43:52

您可以使用符合NSObject的单例NSObject,这样就可以观察任何东西,甚至是更老的苹果对象,比如进度。

代码语言:javascript
复制
class appData : NSObject , ObservableObject {
    static let shared = appData()
    @Published var localItems = Array<AVPlayerItem>()
    @Published var fractionCompleted : Double = 0
    @Published var downloaded : Bool = false
    @Published var langdentifier = UserDefaults.standard.value(forKey: "lang") as? String ?? "en" {
        didSet {
            print("AppState isLoggedIn: \(langIdentifier)")
        }
    }
    var progress : Progress?
    override init() {
    }
}

然后您可以在代码中的任何地方使用它,如下所示:

代码语言:javascript
复制
appData.shared.langIdentifier == "en" ? .leading : .trailing
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66848070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档