我使用的核心数据,我有一个基本的文件夹结构表示。每个项目(文件/文件夹)是表中的一行。每个项目都有一个name
财产,也指向这是它的父项的可选关系。我试图写一个函数,它接受在表示的路径(例如["myFolder", "mySubfolder", "mySubSubfolder", "myFile"]
)一个字符串数组,并返回其在该路径中找到的项。在英语中,我想问核心数据是“给我他的名字是myFile
,其父的名字是mySubSubfolder
,其祖父母的名字是mySubfolder
,和其伟大的祖父母的名字是myFolder
所有项目”。描述这种文字的更简单的方法是定义这种情况称为item(at: path)
它说,以核心数据“给我他的名字是path.last
,且其家长满足item(at: path.dropLast())
所有项目”。我在我的心脏,希望有这使得这种可能的谓词的花哨功能,但我新够他们,我无法使用Google我的方式来回答。
我想如果可能的话,而不是构建和运行时解析格式字符串使用强类型的方法。
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
好吧其实我觉得我想通了。没有实际测试过,但还没有概念上它似乎是正确的。下面是它创建适当的谓词字符串的代码:
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"