【问题标题】:Array of structs: UserDefaults, how to use?结构数组:UserDefaults,如何使用?
【发布时间】:2017-08-21 08:35:04
【问题描述】:

我已经检查了所有这些主题:

How to save an array of custom struct to NSUserDefault with swift?

How to save struct to NSUserDefaults in Swift 2.0

STRUCT Array To UserDefaults

我有一个包含一些字符串和另一个结构的结构:MySection。

struct MySection {
  var name: String = ""
  var values: [MyRow] = []
}

还有 MyRow 存储在 MySection.values 中

struct MyRow {
  var value: String = ""
  var quantity: String = ""
  var quantityType: String = ""
  var done: String = ""
}

两个数组供使用

var arraySection: [MySection] = []
var arrayRow: [MyRow] = []

在我的应用程序中,我在这些数组中动态添加了一些值。

有从我的第二个 ViewController 获取数据的委托方法

func returnInfos(newItem: [MyRow], sectionPick: String) {
    arrayRow.append(MyRow())
    arrayRow[arrayRow.count - 1] = newItem[0]
    manageSection(item: sectionPick)
    listTableView.reloadData()
}

还有manageSection函数。

func manageSection(item: String) {
    var i = 0
    for _ in arraySection {
        if arraySection[i].name == item {
            arraySection.insert(MySection(), at: i + 1)
            arraySection[i + 1].values = [arrayRow[arrayRow.count - 1]]
            return
        }
        i += 1
    }
    arraySection.append(MySection())
    arraySection[arraySection.count - 1].name = item
    arraySection[arraySection.count - 1].values = [arrayRow[arrayRow.count - 1]]
}

我的需要是将两个数组的数据存储在 UserDefaults(或者可能是 CoreData ?)中,并在用户返回应用程序时使用这些数据。

我不知道该怎么做,我已经尝试了 3 个主题的方法,但我什至没有做好。

我该怎么做?

谢谢大家!

【问题讨论】:

  • 你链接的最后一篇文章解释得很好。你有什么不明白的?
  • 怎么用,没看懂方法。当调用保存和重新加载函数时..
  • 您编写了一个将结构与[String: Any] 相互转换的方法。这样您就可以将转换后的结构保存到 UserDefaults 中。当您检索它时,您将字典转换回结构。从您阅读的所有这些帖子中展示您尝试过的东西。

标签: swift


【解决方案1】:

由于这两种类型仅包含符合属性列表的类型,因此合适的解决方案是添加代码以将每种类型转换为符合属性列表的对象,反之亦然。

struct MySection {
    var name: String
    var values = [MyRow]()

    init(name : String, values : [MyRow] = []) {
        self.name = name
        self.values = values
    }

    init(propertyList: [String: Any]) {
        self.name = propertyList["name"] as! String
        self.values = (propertyList["values"] as! [[String:String]]).map{ MyRow(propertyList: $0) }
    }

    var propertyListRepresentation : [String: Any] {
        return ["name" : name, "values" : values.map { $0.propertyListRepresentation }]
    }
}

struct MyRow {
    var value: String
    var quantity: String
    var quantityType: String
    var done: String

    init(value : String, quantity: String, quantityType: String, done: String) {
        self.value = value
        self.quantity = quantity
        self.quantityType = quantityType
        self.done = done
    }

    init(propertyList: [String:String]) {
        self.value = propertyList["value"]!
        self.quantity = propertyList["quantity"]!
        self.quantityType = propertyList["quantityType"]!
        self.done = propertyList["done"]!
    }

    var propertyListRepresentation : [String: Any] {
        return ["value" : value, "quantity" : quantity,  "quantityType" : quantityType, "done" : done ]
    }
}

创建几个对象后

let row1 = MyRow(value: "Foo", quantity: "10", quantityType: "Foo", done: "Yes")
let row2 = MyRow(value: "Bar", quantity: "10", quantityType: "Bar", done: "No")

let section = MySection(name: "Baz", values: [row1, row2])

调用 propertyListRepresentation 获取字典 ([String:Any]),可以将其保存到用户默认值。

let propertyList = section.propertyListRepresentation

该部分的娱乐也很容易

let newSection = MySection(propertyList: propertyList)

编辑

仅在从UserDefaults 获取数据时使用propertyList 初始化器,在所有其他情况下使用其他初始化器。

例如替换

@IBAction func addButtonPressed(_ sender: Any) {
    newProducts.append(MyRow(propertyList: ["":""]))
    newProducts[newProducts.count - 1].value = nameTextField.text!
    newProducts[newProducts.count - 1].quantity = quantityTextField.text!
    newProducts[newProducts.count - 1].quantityType = type
    newProducts[newProducts.count - 1].done = "No"
    delegate?.returnInfos(newItem: newProducts, sectionPick: typePick)
    navigationController?.popViewController(animated: true)
}

@IBAction func addButtonPressed(_ sender: Any) {

    let row = MyRow(value: nameTextField.text!,
                    quantity: quantityTextField.text!,
                    quantityType: type,
                    done: "No")
    newProducts.append(row)
    delegate?.returnInfos(newItem: newProducts, sectionPick: typePick)
    navigationController?.popViewController(animated: true)
}

替换

func returnInfos(newItem: [MyRow], sectionPick: String) {
    arrayRow.append(MyRow(propertyList: ["":""]))
    arrayRow[arrayRow.count - 1] = newItem[0]
    manageSection(item: sectionPick)
    listTableView.reloadData()
}

func returnInfos(newItem: [MyRow], sectionPick: String) {
    arrayRow.append(newItem[0])
    manageSection(item: sectionPick)
    listTableView.reloadData()
}

基本上首先创建对象,然后将其附加到数组中。反过来就很麻烦了。

【讨论】:

  • 感谢您的回答。我试图实现你答案的第一部分,现在当我尝试在我的 arraySection 中添加一些东西时,我在这一行出现了一个错误:init(propertyList: [String:String]) { self.value = propertyList["value"]!
  • 有两个初始化器,一个是标准的,一个是第二个,它需要一个字典,其中包含与属性对应的四个键。第二个初始化器应该只用于使用propertyListRepresentation 创建的对象,因为没有检查nil
  • 我已经编辑并发布了我的整个代码,你能帮我吗?我非常不知道如何使它起作用。
  • 我用一个例子更新了答案。再一次,仅当您从/到UserDefaults 获取/设置数据时才使用propertyList 初始化程序。我从属性中删除了所有默认值,因此您必须使用初始化程序传递所有参数。这使代码更加安全和一致。
  • 通过调用propertyListRepresentation设置将对象转换为属性,使用propertyList初始化器创建对象。对于数组,您必须像在 MySection 结构中一样调用 map
猜你喜欢
  • 2018-05-14
  • 2018-02-20
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多