【问题标题】:Displaying & working with Core Data in NSTableView在 NSTableView 中显示和使用核心数据
【发布时间】:2018-12-31 13:03:18
【问题描述】:

背景:几周以来,我一直在自学 Swift、iOS 和 macOS,我一直在尝试为 macOS 构建一个“价格计算器”,该计算器从纸质数据库中获取并使用选定的属性来选择一张纸。用户将能够从属性列表中进行选择,例如:尺寸、重量、表面处理、颜色和品牌。从那里它会使用一般算术计算纸张的价格。

起初我考虑使用 SQLite 或类似的数据库样式程序来填充我的计算器 - 但用户需要能够自己填充 Paper 数据库。因此,我开始使用 Core Data。

问题:我有一个 tableView,它获取核心数据并显示不同论文的可用——或者至少它应该这样做。为了测试,我已经创建了一个“添加纸张”按钮,该按钮生成随机纸张并将其添加到数据库中。我知道这是在创建随机随机纸,因为我能够在输出中显示它。但我真的不知道它是否在节省。

我遇到的问题是,当我尝试刷新表格并将数据显示到 tableView 时......它要么由于 Nil 值而崩溃,要么它没有添加到 tableView。

我得出的结论是,我在表格中显示的数据可能有误 - 或者 - 我没有正确保存数据 - 或者 - 我没有正确获取数据。

iOS 的在线资源仅对 Mac OS 有很大帮助,如果有任何帮助,我们将不胜感激。 我的代码可以在下面找到,提前致谢:注意:我正在使用 CoreData 中的样板 AppDelegate 文件。

在 ViewController 中定义:

private var papers = [FlatPaper]()
private var appDelegate = NSApplication.shared.delegate as! AppDelegate
private let context = (NSApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

添加随机纸张按钮(用于测试):

@IBAction func addPaper(_ sender: NSButton) {
    let data = PaperData()
    let paper = FlatPaper(entity: FlatPaper.entity(), insertInto: context)
    paper.paperSize = data.paperSize
    paper.paperWeight = data.paperWeight
    paper.paperBrand = data.paperBrand
    paper.paperColor = data.paperColor
    paper.paperFinish = data.paperFinish
    paper.paperPrice = data.paperPrice
    appDelegate.saveAction(paper)
    papers.append(paper)
    print("Add Paper Button Pressed. \(paper)")
    refresh()
    tableView.reloadData()
}

扩展 NSTableDelegate 和 NSTableDataSource:

extension ViewController: NSTableViewDataSource, NSTableViewDelegate {

    // Mark: - Specifying how many rows
    func numberOfRows(in tableView: NSTableView) -> Int {
        return papers.count
        }

    // Mark: - Populating the Columns and Rows with Data
    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        let paperSpecs = papers[row]
        
        if tableColumn!.title == "Paper Size" {
            return paperSpecs.paperSize
        } else if tableColumn!.title == "Paper Weight" {
            return paperSpecs.paperWeight
        } else if tableColumn!.title == "Paper Brand" {
            return paperSpecs.paperBrand
        } else if tableColumn!.title == "Paper Color" {
            return paperSpecs.paperColor
        } else if tableColumn!.title == "Paper Finish" {
            return paperSpecs.paperFinish
        } else {
            return paperSpecs.paperPrice
        }
    }

    // Mark: - Refresh Method for reloading all of the data
    private func refresh() {
        do {
            papers = try context.fetch(FlatPaper.fetchRequest())
        } catch let error as NSError {
            print("Could not fetch. \(error), USER INFO: \(error.userInfo)")
        }
    }
}

【问题讨论】:

  • macOS 在线资源:NSTableView。底部是指向 Mac 的 Table View Programming Guide 的链接。
  • 实现 objectValueFor 表示您正在使用 Cocoa Bindings。我猜绑定丢失或不正确。并按照 Joakim 的建议进行更改。他是对的。不相关,但在 addPaper 方法中,在将项目添加到数据源数组并保存上下文后,不要调用 refesh。从最后一个索引创建一个IndexSet 并调用insertRows(at:withAnimation:) 以插入带有动画的表格行。
  • 感谢这两个!我将不得不访问那个 Table View Programming Guide 资源。另外,很高兴知道 objectValueFor 用于 Cocoa 绑定。我以前尝试过使用它,但我想我从未将其切换回来。在继续使用 Core Data 之前,我似乎需要更好地掌握 Swift。

标签: swift macos core-data nstableview


【解决方案1】:

tableview:objectValueFor 中,您应该使用 row 参数从数组中获取纸张规格对象,而不是创建一个新的(空)实例。

let paperSpecs = papers[row]

您可能还想查看NSFetchedResultsController,它在处理核心数据和表格视图时非常有用。

【讨论】:

  • 我已经更改了这一行,但 tableView 仍然没有更新。这让我相信这就是我在表格中呈现数据的方式。今晚/明天我将对此进行调查,并可能再次尝试 NSFetchedResults 控制器。希望这次我能有更好的运气。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
相关资源
最近更新 更多