簡體   English   中英

SwiftUI,AppStorage 和在 TabViews 中使用 Picker

[英]SwiftUI, AppStorage and using Picker in TabViews

我正在嘗試使用 AppStorage 跨多個視圖使用選擇器保存少量數據。 但是,我遇到的問題是,當我 select 一個值並鏈接到 AppStorage 時,它會更改所有其他值。 我想要的是為多個視圖中的每個選擇保存值。 如果我使用 @State 變量,選擇工作正常,但當我關閉並重新打開應用程序時,這些值不會被保存。 我很確定我需要將每個選擇發送到它自己的 @AppStorage 變量,但我很難弄清楚如何做到這一點。

struct Animals: Identifiable {
    var id = UUID().uuidString
    var name: String
    var animalTypes: [AnimalTypes]
}
var allAnimals = [
    Animals(name: "fred", animalTypes: [.shiba, .lab]),
    Animals(name: "barney", animalTypes: [.shiba, .dobberman, .lab]),
    Animals(name: "molly", animalTypes: [.snowshoe, .burmese, .bengal]),
    Animals(name: "bob", animalTypes: [.burmese]),
    Animals(name: "wilma", animalTypes: [.snowshoe, .bengal]),
]

enum AnimalTypes: String, CaseIterable, Codable {
    // Dog Breeds
    case shiba, lab, dobberman
    // Cat Breeds
    case snowshoe, burmese, bengal
}

struct AnimalsView: View {

    
    @State var animals: Animals!
    
    var body: some View {
        TabView {
            ForEach(allAnimals) { animal in
                AnimalSelectionView(animals: animal)
                .tag(animal.name)
            }
        }
        .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
    }
}

struct AnimalSelectionView: View {
    
    @AppStorage("selection") var animalSelection: Int = 0 // Saves the same value across all pickers (how to save individual values?)
//    @State private var animalSelection: Int = 0 // Sets value for each picker in each tabview, but doesn't save
    @State var animals: Animals!
    
    var body: some View {
        VStack {
            if animals.animalTypes.count <= 1 {
                Text("\(animals.animalTypes[0].rawValue)")
            } else {
                Text("\(animals.animalTypes[animalSelection].rawValue)")
            }
            
            if animals.animalTypes.count > 1 {
                Picker(selection: $animalSelection, label: Text("Select Animal Type")) {
                    ForEach(0 ..< animals.animalTypes.count, id:\.self) { item in
                        Text("\(item + 1)")
                            .font(.caption)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
                .frame(width: 100, height: 17)
            }
        }
    }
}

我看到您已決定在Animals class 上創建一個名為id的屬性。 令人高興的是,這是用於為每個Animals object 保存唯一的UserDefaults值的完美工具。

你可以這樣做:

struct AnimalSelectionView: View {

    @AppStorage var animalSelection: Int
    @State var animals: Animals

    init(animals: Animals) {
        self.animals = animals
        // The below line simply assigns the key which should be used to access your
        // desired variable. This way, it can be keyed specifically to your `Animals`
        // id value.
        self._animalSelection = AppStorage(wrappedValue: 0, "selection-\(animals.id)")
    }

    ...

}

請記住,如果您實例化兩個在 init 中傳遞了相同 arguments 的不同對象,您將無法檢索相同的值。

例子:

let fred = Animals(name: "fred", animalTypes: [.shiba, .lab])
let fred2 = Animals(name: "fred", animalTypes: [.shiba, .lab])

為清楚起見編輯:

在這里, fredfred2基本相同,但每個Animals實例的id屬性都不同。 因此,如果您嘗試使用另一個的id訪問一個的選擇值,您將不會收到正確的值。 您必須保留確切的Animals實例以訪問您存儲在UserDefaults中的值,或者至少根據需要保留其id 此規則適用於所有應用程序會話。 如果您實例化Animals object 然后退出並重新啟動應用程序,當重新實例化相同的Animals object 時,它將根據您的定義分配不同的idAnimals.id = UUID().uuidString

為了在應用程序會話中保留它們的id ,您可以將動物存儲在CoreDataUserDefaults中,授予它們 static id ,或者根據Animals屬性生成一個id

創建一個 static id看起來像這樣:

`Animals(id: "animal-fred", name: "fred", animalTypes: [.shiba, .lab])`

根據它們的屬性生成一個id可能看起來像:

Animals: Identifiable {
    var id: {
        // We concatenate the name with each of the `AnimalsTypes`
        // by mapping the `AnimalsTypes` to their relevant strings
        // and joining them by a comma.
        // The resulting `id` might look like:
        // "fred-shiba,lab"
        return name + "-" + animalTypes.map { $0.rawValue }.joined(separator: ",")
    }
    var name: String
    var animalTypes: [AnimalTypes]
}

基於Animals屬性生成id的方法效果很好,盡管如果您創建兩個具有完全相同屬性的Animals ,您的邏輯將無法區分它們,因為它們將生成相同的id 然后他們將在UserDefaults中獲取並設置相同的值,因為他們將共享相同的密鑰。

如果您打算讓這些動物由您的應用程序的用戶動態創建,則需要將它們存儲在CoreDataUserDefaults中。 但是,如果您的動物將全部由您創建,您可以靜態定義 ID 或根據Animals屬性生成它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM