Swift 3核心数据指南 [英] Guidance on Core Data with Swift 3

查看:100
本文介绍了Swift 3核心数据指南的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Not looking for code (wouldn't hurt though) just looking to know how I should go about this. I have an app which is like a blog reader. I have information in a MYSQL database which is taken with JSON, placed in a jsonArray and then placed in an array to be shown in a table view. In that table view I generally have all my objects in 1 section. Each row/object has a button when clicked it moves that row into another section. I also have a search controller to search through the main section (Section 1).

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

How do I save the order or position of the rows to Core Data?

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

For example: I have 0 rows in Section 0 and 5 rows in Section 1, I click the button on one of the rows in Section 1 and it moves that row to Section 0, now Section 0 has 1 row while Section 1 has 4 rows. How do I save this new tableview order to Core Data? I just want to save the rows positions, so the app remembers which section that selected row was in.

是否在该部分中保存该行的indexPath? 添加实体和属性时,该怎么保存?

Do I save the indexPath of the row in the section? When adding an entity and attributes, what do I use to save?

而且,它是一个mysql读取器,因此当重新加载tableview并添加新内容时,由于tableview将从核心数据中读取数据,它还会显示吗?

Also, its a mysql reader so when the tableview is reloaded and a new content is added, will it still show since the tableview will be reading from core data?

我正在学习Core Data(Swift 3代码),但在将此应用程序使用它时遇到了麻烦.

I'm learning Core Data (Swift 3 code) but just having trouble using it for this app.

感谢您的帮助!

推荐答案

如果不需要从MySQL数据库保存整个数据,请使用UserDefaults保存订购数据.定义一个仅包含dataId和indexPath的类:

Use UserDefaults to save the ordering data if you don't need to save the whole data from MySQL database. Define a class only contains dataId and 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]

使用保存功能保存键"并通过DataOrdering(默认值:键")将其读回

Use save function to save with a "key" and read it back by DataOrdering(defaults: "key")

已更新

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

Added codes for a view controller to use this class:

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
    }


}

这篇关于Swift 3核心数据指南的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆