首页 > 解决方案 > 当您的数据源是 Results 对象时,如何在表格视图中移动行?

问题描述

我有一个从结果对象中提取数据的表视图。但是,因为您不能在 Results 对象中移动项目,所以我必须使用 List 对象在表视图中移动行。

但是,如果您将数据从 Results 转换为 List 对象(将 List 对象用于表格视图),则 List 对象不再是反应式的。这意味着它只包含 Results 对象中的数据副本。

所以我的问题是:当您的表格视图从结果对象中提取数据时,您如何在表格视图中移动行?

标签: iosswiftrealm

解决方案


您需要为模型添加索引属性。要么,要么您需要定义一个新的 Realm 类,该类具有索引属性和对您要定义的对象的引用。我会推荐第一个,因为它更简单。这是执行此操作的一种方法。

我会实现一个协议,以便您可以将相同的逻辑应用于其他模型。

protocol IndexableObject: AnyObject {
    var index: Int { get set }
}

现在符合协议。

class MovingObject: Object, IndexableObject {
    @objc dynamic var name: String = ""
    @objc dynamic var index: Int = 0
}

如果您向结果添加扩展名,那将会很有帮助。基本上你想要做的是提取索引在 [fromIndex, toIndex] 范围内的元素并将它们存储在一个数组中,这样你就可以在执行“移动”后更新索引。过滤器确保您只更新必要的索引,而不是结果集中的所有元素。

extension Results where Element: IndexableObject {

    func moveObject(from fromIndex: Int, to toIndex: Int) {

        let min = Swift.min(fromIndex, toIndex)
        let max = Swift.max(fromIndex, toIndex)

        let baseIndex = min

        var elementsInRange: [Element] = filter("index >= %@ AND index <= %@", min, max)
            .map { $0 }

        let source = elementsInRange.remove(at: fromIndex - baseIndex)
        elementsInRange.insert(source, at: toIndex - baseIndex)

        elementsInRange
            .enumerated()
            .forEach { (index, element) in
                element.index = index + baseIndex
            }
    }
}

您的 UIableViewController 中的用法会像这样。

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {

    let realm = try! Realm()

    try! realm.write {
        objects.moveObject(from: sourceIndexPath.row, to: destinationIndexPath.row)
    }
}

只需确保按索引排序并将对象链接到通知块中的 UITableView 即可。您应该在 Realm 的在线文档中找到有关如何完成此操作的大量信息。

lazy var objects: Results<MovingObject> = {
    let realm = try! Realm()
    return realm.objects(MovingObject.self)
        .sorted(by: \.index, ascending: true)
}()

func observeObjects() {
    notificationToken = objects.observe { [weak self] change in
        self?.processChange(change)
    }
}

推荐阅读