与条件NSPredicate基于递归关系 - 斯威夫特 - 核心数据

问题描述 投票:2回答:2

我使用的核心数据,我有一个基本的文件夹结构表示。每个项目(文件/文件夹)是表中的一行。每个项目都有一个name财产,也指向这是它的父项的可选关系。我试图写一个函数,它接受在表示的路径(例如["myFolder", "mySubfolder", "mySubSubfolder", "myFile"])一个字符串数组,并返回其在该路径中找到的项。在英语中,我想问核心数据是“给我他的名字是myFile,其父的名字是mySubSubfolder,其祖父母的名字是mySubfolder,和其伟大的祖父母的名字是myFolder所有项目”。描述这种文字的更简单的方法是定义这种情况称为item(at: path)它说,以核心数据“给我他的名字是path.last,且其家长满足item(at: path.dropLast())所有项目”。我在我的心脏,希望有这使得这种可能的谓词的花哨功能,但我新够他们,我无法使用Google我的方式来回答。

swift recursion core-data nspredicate recursive-query
2个回答
1
投票

我想如果可能的话,而不是构建和运行时解析格式字符串使用强类型的方法。

import Foundation

func predicateMatchingPath(_ path: [String]) -> NSPredicate {
    var path = path
    guard let last = path.popLast() else {
        return NSPredicate(value: false)
    }

    var ancestorKeyPath = ""
    let nameSuffix = "name"
    var predicates = [NSPredicate]()

    predicates.append(NSComparisonPredicate(
        leftExpression: NSExpression(forKeyPath: ancestorKeyPath + nameSuffix),
        rightExpression: NSExpression(forConstantValue: last),
        modifier: .direct, type: .equalTo, options: []))

    while let anscestor = path.popLast() {
        ancestorKeyPath.append("parent.")
        predicates.append(NSComparisonPredicate(
            leftExpression: NSExpression(forKeyPath: ancestorKeyPath + nameSuffix),
            rightExpression: NSExpression(forConstantValue: anscestor),
            modifier: .direct, type: .equalTo, options: []))
    }

    // Make sure the most distant ancestor is a root.
    predicates.append(NSComparisonPredicate(
        leftExpression: NSExpression(forKeyPath: ancestorKeyPath + "parent"),
        rightExpression: NSExpression(forConstantValue: nil),
        modifier: .direct, type: .equalTo, options: []))

    return NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
}

print(predicateMatchingPath(["myFolder", "mySubfolder", "mySubSubfolder", "myFile"]))

// Output:
name == "myFile" AND parent.name == "mySubSubfolder" AND parent.parent.name == "mySubfolder" AND parent.parent.parent.name == "myFolder" AND parent.parent.parent.parent == nil

0
投票

好吧其实我觉得我想通了。没有实际测试过,但还没有概念上它似乎是正确的。下面是它创建适当的谓词字符串的代码:

var predicateString = ""
var i = 0
for pathComponent in path.reversed() {
    predicateString += "name == \(pathComponent) && parent"
    for _ in 0 ..< i {
        predicateString += ".parent"
    }
    i += 1
    guard i != path.count else { continue }
    predicateString += "."
}
predicateString += " == nil"

© www.soinside.com 2019 - 2024. All rights reserved.