【问题标题】:Guidance on Core Data with Swift 3Swift 3 核心数据指南
【发布时间】:2017-05-15 16:41:05
【问题描述】:

不寻找代码(虽然不会受到伤害)只是想知道我应该如何去做。我有一个类似于博客阅读器的应用程序。我在 MYSQL 数据库中有信息,该数据库采用 JSON 格式,放置在 jsonArray 中,然后放置在数组中以显示在表格视图中。在那个表格视图中,我通常将所有对象放在一个部分中。每行/对象都有一个按钮,单击它会将该行移动到另一个部分。我还有一个搜索控制器来搜索主要部分(第 1 部分)。

如何将行的顺序或位置保存到 Core Data?

例如:我在第 0 节中有 0 行,在第 1 节中有 5 行,我单击第 1 节中其中一行上的按钮,然后将该行移至第 0 节,现在第 0 节有 1 行,而第 1 节有 4 行。如何将这个新的 tableview 订单保存到 Core Data?我只想保存行位置,以便应用记住所选行所在的部分。

是否保存该部分中行的 indexPath? 添加实体和属性时,我用什么来保存?

另外,它是一个 mysql 阅读器,所以当重新加载 tableview 并添加新内容时,它是否仍会显示,因为 tableview 将从核心数据读取?

我正在学习 Core Data(Swift 3 代码),但在使用它时遇到了问题。

感谢您的帮助!

【问题讨论】:

    标签: ios json swift uitableview core-data


    【解决方案1】:

    如果您不需要保存 MySQL 数据库中的全部数据,请使用 UserDefaults 保存订购数据。定义一个只包含dataId和indexPath的类:

    class DataOrdering: NSObject, NSCoding {
    
        var indexPath: IndexPath?
        var dataId: String?
    
        init(dataId: String, indexPath: IndexPath) {
            super.init()
            self.dataId = dataId
            self.indexPath = indexPath
        }
    
        required init(coder aDecoder: NSCoder) {
    
            if let dataId = aDecoder.decodeObject(forKey: "dataId") as? String {
                self.dataId = dataId
            }
    
            if let indexPath = aDecoder.decodeObject(forKey: "indexPath") as? IndexPath {
                self.indexPath = indexPath
            }
    
        }
    
        func encode(with aCoder: NSCoder) {
            aCoder.encode(dataId, forKey: "dataId")
            aCoder.encode(indexPath, forKey: "indexPath")
        }
    
        func save(defaults key: String) -> Bool {
    
            let defaults = UserDefaults.standard
            let savedData = NSKeyedArchiver.archivedData(withRootObject: self)
            defaults.set(savedData, forKey: key)
            return defaults.synchronize()
    
        }
    
        convenience init?(defaults key: String) {
    
            let defaults = UserDefaults.standard
            if let data = defaults.object(forKey: key) as? Data,
                let obj = NSKeyedUnarchiver.unarchiveObject(with: data) as? DataOrdering,
                let dataId = obj.dataId,
                let indexPath = obj.indexPath {
                self.init(dataId: dataId, indexPath: indexPath)
            } else {
                return nil
            }
    
        }
    
        class func allSavedOrdering(_ maxRows: Int) -> [Int: [DataOrdering]] {
    
            var result: [Int: [DataOrdering]] = [:]
            for section in 0...1 {
                var rows: [DataOrdering] = []
                for row in 0..<maxRows {
                    let indexPath = IndexPath(row: row, section: section)
                    if let ordering = DataOrdering(defaults: indexPath.defaultsKey) {
                        rows.append(ordering)
                    }
                    rows.sort(by: { $0.indexPath! < $1.indexPath! })
                }
                result[section] = rows
            }
    
            return result
    
        }
    
    }
    

    游乐场样本:

    let data = DataOrdering(dataId: "1", indexPath: IndexPath(row: 0, section: 0))
    
    let savedData = NSKeyedArchiver.archivedData(withRootObject: data)
    let obj = NSKeyedUnarchiver.unarchiveObject(with: savedData) as? DataOrdering
    obj?.dataId // print: "1"
    obj?.indexPath // print: [0,0]
    

    使用 save 函数通过“key”保存并通过 DataOrdering 读回(默认值:“key”)

    更新

    为视图控制器添加代码以使用此类:

    extension IndexPath {
        var defaultsKey: String { return "data_ordering_\(section)_\(row)" }
    }
    
    class ViewController: UITableViewController {
    
        var data: [Any]?
        var items: [[Any]]?
    
        func fetchData() {
    
            // request from remote or local
            data = [1, 2, 3, "a", "b", "c"] // sample data
    
            // Update the items to first section has 0 elements,
            // and place all data in section 1
            items = [[], data ?? []]
    
            // apply ordering
            applySorting() { "\($0)" }
    
            // save ordering
            saveSorting() { "\($0)" }
    
            // refresh the table view
            tableView.reloadData()
    
        }
    
        func applySorting(_ dataIdBlock: (Any) -> String) {
    
            // get all saved ordering
            guard let data = self.data else { return }
            let ordering = DataOrdering.allSavedOrdering(data.count)
    
            var result: [[Any]] = [[], []]
    
            for (section, ordering) in ordering {
                guard section <= 1 else { continue } // make sure the section is 0 or 1
                let rows = data.filter({ obj -> Bool in
                    return ordering.index(where: { $0.dataId == .some(dataIdBlock(obj)) }) != nil
                })
                result[section] = rows
            }
    
            self.items = result
    
        }
    
        func saveSorting(_ dataIdBlock: (Any) -> String) {
    
            guard let items = self.items else { return }
    
            for (section, rows) in items.enumerated() {
                for (row, item) in rows.enumerated() {
                    let indexPath = IndexPath(row: row, section: section)
                    let dataId = dataIdBlock(item)
                    let ordering = DataOrdering(dataId: dataId, indexPath: indexPath)
                    ordering.save(defaults: indexPath.defaultsKey)
                }
            }
    
        }
    
        @IBAction func buttonMoveToSectionTapped(_ sender: UIButton) {
    
            // if the sender's tag is row index
            // or you can get indexPath by tableView.indexPath(for: cell) function too
            let row = sender.tag
    
            // move this item from section 1 to section 0 (last position)
            if let item = items?[1].remove(at: row) {
                items?[0].append(item)
            }
    
            // Save all sorting
            saveSorting() { "\($0)" }
    
            tableView.reloadData() // refresh table view
    
        }
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            return self.items?.count ?? 0
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.items?[section].count ?? 0
        }
    
    
    }
    

    【讨论】:

    • 谢谢!出于某种原因,我认为我需要核心数据,但你是对的 NSUserDefaults 是正确的方法,因为我只需要保存表格视图的顺序。快速问题:您向我展示的代码是保存 indexPath 但保存是如何工作的?我在哪里保存该行在哪个部分?
    • 我更新了答案以添加代码如何为您使用该类@BroSimple
    • 嘿抱歉,代码不起作用,表格视图返回为空,我使用 saveSorting() { "($0)" } 保存并在 ViewDidLoad 中使用 fetchData()
    • 我还在“ordering.save(defaults: indexPath.defaultsKey)”行上收到警告,说“调用'save(defaults:)'的结果未使用”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多