【问题标题】:How to implement userDefaults with a Global Variable array如何使用全局变量数组实现 userDefaults
【发布时间】:2020-05-14 21:35:29
【问题描述】:

我有一个空数组设置为全局变量,其中填充了表格视图中的数组项。这用于填充另一个表视图。这些数据需要持久化,以便当用户返回应用程序时,他们的 tableview 数据处于与离开时相同的状态,即使用数组中的数据填充。

虽然我已经寻找了几十个教程和示例。我自己也破解了它以使其工作,每次我重新加载应用程序时,数组都是空的。如何让该全局变量数组保留它的数组数据?

var sharedData = [String]()

这是我的第一个 VC,其中我有 UserDefaults 的设置功能。每次对数组进行更改时,我都会执行我的 saveArray() 函数。每次我需要从数组中加载时,我都会执行 retrieveArray() 函数。

import UIKit

var sharedData = [String]()
struct Keys {

    static let arrayKey = "arrayKey"
}

let defaults = UserDefaults.standard

func saveArray() {
    defaults.set(sharedData, forKey: Keys.arrayKey)
}

func retrieveArray() {
    var savedData = defaults.object(forKey: Keys.arrayKey) as? [String] ?? []
    savedData.append(contentsOf: sharedData)
}

class ViewController: UIViewController {

    var effect:UIVisualEffect!

    @IBOutlet weak var searchBar: UISearchBar!

    @IBOutlet var tableView: UITableView!

    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    @IBOutlet weak var visualEffectView: UIVisualEffectView!

    let materialData = ["One", "Two", "Three", "Four"]

    var searchMaterial = [String]()
    var searching = false

    @IBAction func favoritesButtonArrayUpdate(_ sender: UIBarButtonItem) {
        print(sharedData)

    }

    override func viewDidLoad() {
        super.viewDidLoad()

    tableView.delegate = self
        tableView.dataSource = self

        saveArray()
        retrieveArray()

        print(sharedData)

    }

extension ViewController: UITableViewDelegate {

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        tableView.deselectRow(at: indexPath, animated: true)
        print(self.materialData[indexPath.row], "selected!")
    }

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

        let favorite = UITableViewRowAction(style: .default, title: "Favorite") { (action, indexPath) in

            var data: String

            if self.searching {
                data = self.searchMaterial[indexPath.row]
            } else {
                data = self.materialData[indexPath.row]
            }

            sharedData.append(data)
            saveArray()
            print(sharedData)

        }

        favorite.backgroundColor = UIColor.orange
        return [favorite] 
    }

}

这是我的第二个 VC,它显示存储在全局变量数组 sharedData 中的数组数据。在对数组进行更改并从数组中提取数据时,我再次添加了所有 func。

import UIKit

class FavoritesViewController: UIViewController {

    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        saveArray()
        retrieveArray()
    }
}

extension FavoritesViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        retrieveArray()
        return sharedData.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        retrieveArray()
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.numberOfLines = 0
        cell.textLabel?.text = sharedData[indexPath.row]
        return cell
    }

    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {

            sharedData.remove(at: indexPath.row)
            saveArray()
            tableView.beginUpdates()
            tableView.deleteRows(at: [indexPath], with: .automatic)
            tableView.endUpdates()
        }
    }
}

【问题讨论】:

    标签: arrays swift variables global userdefaults


    【解决方案1】:

    问题可能出在这里:

    let savedData: [String] = userDefaults.object(forKey: "arrayKey") as? [String] ?? []
    

    尝试更改它:

    let savedData: [String] = userDefaults?.object(forKey: "arrayKey") as? [String] ?? []
    

    这是因为必须解包 UserDefaults 才能引用成员对象。试试看

    【讨论】:

    • Xcode 响应“不能在 'UserDefaults' 类型的非可选值上使用可选链接”并建议删除添加的“?”
    • 那么原始版本到底有什么问题? (也许用确切的问题更新问题)。 “我需要在重新启动应用程序时恢复阵列中的数据”到底是什么意思,您是否希望它们在重新启动时出现? (“恢复”有点难以理解)。你打算在哪里使用 userDefaults ?也许你应该考虑使用suiteName。查看 Apple 文档
    • 没关系。如果您编写 userDefaults.set(sharedData, forKey: "arrayKey") 您正在使用 sharedData 中的数据填充 userDefaults 的键“arrayKey”,但如果您刚刚启动应用程序,sharedData 是空的,所以如果您尝试,立即之后,用 let savedData: [String] = userDefaults.object(forKey: "arrayKey") 填充 savedDate 它将是空的,因为 userDefaults 中的 "arrayKey" 是空的。因此,当用户输入填充 shareData 时,您需要使用 shareData 在 userdefaults 中填充“arrayKey”,然后在应用启动时,从 userdefaults 填充 savedData(开始时的某处)。
    • 字符不够清晰。我的意思是,您必须在不同的时刻填充 userdefaults 然后填充 savedData 否则如果您刚刚启动应用程序(A = B,B = C,所以 A = C,如果 A = 空,C = 空)。因此,找到将 sharedData 存储在 userDefaults 中的合适时机,以及使用 Userdefaults 内容填充 savedData 的合适时机。如果你有它,也许可以在启动类中做第二件事,或者在启动的场景委托中做第二件事,或者根据你的项目做其他事情。
    • 我把它整理好了。无需套件名称:。我只需要正确处理工作流程。我试图把它复杂化太多。感谢您的帮助!
    【解决方案2】:

    根据MrHim 的建议,我从我的第一个VC 的viewDidLoad 中删除了saveArray 和retrieveArray 函数,并将retrieveArray 留在了我的第二个VC 的viewDidLoad 中。在我的 viewDidLoads 中有 saveArray 是用空数据覆盖数组。然后我需要在我的第二个 VC 中的适当位置检索数组数据。然后在我的 numberOfRowsInSection 中,我删除了 retrieveArray。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 2023-04-07
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-11
      相关资源
      最近更新 更多