Swift TableView插入新行

时间:2017-08-04 09:25:13

标签: swift uitableview core-data

我有一个从核心数据中获取数据的TableView。

保存数据后,它们将作为第一行插入。

这是我用来保存数据的代码(我没有使用fetch控制器,因为我没有获取任何数据,只是加载它们,这是因为我加载的日期来自一个很多关系)

swimToConnect.addToMaterialsLocal(materialLocal)
    ad.saveContext()

        // Adding the new row to update the tableView
        let MyMaterialsVC = self.presentingViewController?.presentingViewController?.presentingViewController as! MyMaterialsVC
        MyMaterialsVC.myMaterials.insert(materialLocal, at: 0)
        MyMaterialsVC.tableView.insertRows(at: [NSIndexPath(row: 0, section: 0) as IndexPath], with: .none)
        MyMaterialsVC.dismiss(animated: true, completion: nil)
    }

所以我想知道是否有办法插入按日期排序的行。 我按照日期订购了它们:

var swim: SwimminPool! {
    didSet {
        myMaterials = (swim.materialsLocal?.allObjects as! [MaterialLocal]).sorted(by: {$0.createdAtLocal! > $1.createdAtLocal!})
    }
}

创建时间是用户添加日期选择器的日期。 当我保存新数据显然它们显示在第一行,但如果我关闭控制器然后重新进入,那么数据将根据日期顺序显示。

有没有办法在我保存数据后立即以正确的顺序订购数据?

谢谢。

3 个答案:

答案 0 :(得分:0)

将此更改为以下

swimToConnect.addToMaterialsLocal(materialLocal)
    ad.saveContext()

        // Adding the new row to update the tableView
        let MyMaterialsVC = self.presentingViewController?.presentingViewController?.presentingViewController as! MyMaterialsVC
        MyMaterialsVC.myMaterials.insert(materialLocal, at: 0)
        MyMaterialsVC.myMaterials = (swim.materialsLocal?.allObjects as! [MaterialLocal]).sorted(by: {$0.createdAtLocal! > $1.createdAtLocal!})
        MyMaterialsVC.tableView.reloadData()
        MyMaterialsVC.dismiss(animated: true, completion: nil)
    }

答案 1 :(得分:0)

此问题的最佳解决方法是使用NSFetchedResultsController。它负责有效地插入和删除项目,并使用NSPredicate对它们进行排序。 您可以在Xcode中创建一个主详细信息应用程序模板并选中核心数据框,然后Xcode使用FetchedResultsController创建一个示例应用程序,在那里您可以看到它是如何工作的。

答案 2 :(得分:0)

这是RandomAccessCollection的扩展,它以非常有效的方式返回新项目的排序集合中的插入索引。好处是您不需要重新加载整个表视图。

extension RandomAccessCollection {
    func insertionIndex(for predicate: (Element) -> Bool) -> Index {
        var slice : SubSequence = self[...]

        while !slice.isEmpty {
            let middle = slice.index(slice.startIndex, offsetBy: slice.count / 2)
            if predicate(slice[middle]) {
                slice = slice[index(after: middle)...]
            } else {
                slice = slice[..<middle]
            }
        }
        return slice.startIndex
    }
}

你可以使用它:

let insertionIndex = MyMaterialsVC.myMaterials.insertionIndex(for: { $0.createdAtLocal! < materialLocal.createdAtLocal!})
MyMaterialsVC.myMaterials.insert(materialLocal, at: insertionIndex)
MyMaterialsVC.tableView.insertRows(at: [IndexPath(row: insertionIndex, section: 0)], with: .none)
MyMaterialsVC.dismiss(animated: true, completion: nil)