0

在我监督的一个项目中查看一些 Swift 代码时,我遇到了这个问题:

return (realm?.objects(ExerciseDBObject.self).filter("isDeleted == false")) as! Results<ExerciseDBObject>

作为 JVM/Python/JS 程序员,让我印象深刻的是filter("isDeleted == false")一点。据说,这段代码工作正常:它过滤了没有删除的练习,但它是一个字符串。这是如何运作的?

我没有使用过 Swift,当我在谷歌上搜索时,我只是偶然发现了文档,String#filter这似乎暗示我通常会将那段代码编写为filter({!$0.isDeleted}).

字符串的isDeleted位指的是对象上的一个道具。Swift 如何避免将它绑定到也被调用的某个变量isDeleted(如果存在,它不在此代码块中)?

4

2 回答 2

3

它正在使用:

// MARK: Filtering
/**
 Returns a `Results` containing all objects matching the given predicate in the collection.
 - parameter predicateFormat: A predicate format string, optionally followed by a variable number of arguments.
 */
func filter(_ predicateFormat: String, _ args: Any...) -> Results<Element>

来源:RealmCollectiton

在引擎盖下,它正在使用NSPredicate(format:),它通过简化和避免每次写入来“隐藏”它NSPredicate(format: ...),并且也应该使用 KeyPath。在Predicate Format String Syntax中更多地解释你可以用它做什么。

不是

func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]

Sequence

这里有一个示例代码来说明/模仿:

class TestClass: NSObject {
    @objc var title: String
    init(title: String) {
        self.title = title
        super.init()
    }
    override var description: String {
        "TestClass - title: \(title)"
    }
}

let objects: [TestClass] = [TestClass(title: "Title1"), TestClass(title: "Title2")]

// In a "Swifty way
let searchedText = "Title1"
let filtered1 = objects.filter {
    $0.title == searchedText
}
print("filtered1: \(filtered1)")

// With a NSPredicate, which is more Objective-C (filtering on NSArray for instance)
// But also there is a translation with Core-Data, and then fetching optimization
let filtered2 = objects.filter {
    NSPredicate(format: "title == 'Title1'").evaluate(with: $0)
}
print("filtered2: \(filtered2)")
// Same, but with avoiding hard coding strings
let filtered3 = objects.filter {
    NSPredicate(format: "%K == %@", #keyPath(TestClass.title), searchedText).evaluate(with: $0)
}
print("filtered3: \(filtered3)")

extension Sequence {
    func filter(_ predicateFormat: String, _ args: Any...) -> [Element] {
        let predicate = NSPredicate(format: predicateFormat, argumentArray: args)
        return self.filter({ predicate.evaluate(with: $0) })
    }
}

// With an extension similar to what does Realm
let filtered4 = objects.filter("title == 'Title1'")
print("filtered4: \(filtered4)")

// With an extension similar to what does Realm, and less hard coded string (cf filtered3 construction)
let filtered5 = objects.filter("%K == %@", #keyPath(TestClass.title), searchedText)
print("filtered5: \(filtered5)")

带输出:

$>filtered1: [TestClass - title: Title1]
$>filtered2: [TestClass - title: Title1]
$>filtered3: [TestClass - title: Title1]
$>filtered4: [TestClass - title: Title1]
$>filtered5: [TestClass - title: Title1]
于 2021-10-15T17:43:18.787 回答
1

您可能正在查看“Realm”的一个功能,我认为它是一种用于处理存储对象的工具,而不是 Swift 的一个功能。

这种情况下的问题是“什么是领域?.objects(...) 返回?”。猜测我会说它不是字符串......它是具有自定义定义的其他对象,filter它知道如何解析 aString并将其用作数据获取操作的查询。

这是多态性上的方法filter。它可以根据被调用的实体的类做不同的事情。

于 2021-10-15T17:39:38.683 回答