美文网首页Hacking with iOS: SwiftUI Edition
SwiftUI Core Data:使用 NSPredicate

SwiftUI Core Data:使用 NSPredicate

作者: 韦弦Zhy | 来源:发表于2020-05-29 18:35 被阅读0次

    \color{red}{\Large \mathbf{Hacking \quad with \quad iOS: SwiftUI \quad Edition}}

    {\Large \mathbf{Core \ Data}}

    Filter @FetchRequest - 韦弦zhy

    当我们使用SwiftUI的@FetchRequest属性包装器时,我们可以提供一个排序描述符数组来控制结果的顺序,但是我们也可以提供NSPredicate来控制应显示哪些结果。谓词是简单的测试,该测试将应用于我们的Core Data实体中的每个对象——只有通过测试的对象才会包含在结果数组中。

    NSPredicate的语法不是您可以轻易猜到的,但实际上,您只会想要几种谓词,因此它并不像您想的那样糟糕。

    要尝试一些谓词,请创建一个名为Ship的新实体,该实体具有两个字符串属性:“name”和“universe”。

    现在将ContentView.swift修改为:

    import CoreData
    import SwiftUI
    
    struct ContentView: View {
        @Environment(\.managedObjectContext) var moc
        @FetchRequest(entity: Ship.entity(), sortDescriptors: [], predicate: nil) var ships: FetchedResults<Ship>
    
        var body: some View {
            VStack {
                List(ships, id: \.self) { ship in
                    Text(ship.name ?? "Unknown name")
                }
    
                Button("Add Examples") {
                    let ship1 = Ship(context: self.moc)
                    ship1.name = "Enterprise"
                    ship1.universe = "Star Trek"
    
                    let ship2 = Ship(context: self.moc)
                    ship2.name = "Defiant"
                    ship2.universe = "Star Trek"
    
                    let ship3 = Ship(context: self.moc)
                    ship3.name = "Millennium Falcon"
                    ship3.universe = "Star Wars"
    
                    let ship4 = Ship(context: self.moc)
                    ship4.name = "Executor"
                    ship4.universe = "Star Wars"
    
                    try? self.moc.save()
                }
            }
        }
    }
    

    现在,我们可以点击按钮,将一些样本数据注入Core Data,但是现在我们没有谓词。为了解决这个问题,我们需要用某种可以应用于我们的对象的测试谓词来代替nil

    例如,我们可以要求来自 Star Wars 的船只,如下所示:

    @FetchRequest(entity: Ship.entity(),
                  sortDescriptors: [],
                  predicate: NSPredicate(format: "universe == 'Star Wars'")
    ) var ships: FetchedResults<Ship>
    

    如果您的数据包含引号,那将变得很复杂,因此更常见的是使用特殊的语法:“%@”表示“在此处插入一些数据”,并允许我们将数据作为谓词的参数而不是内联。

    因此,我们可以这样写:

    NSPredicate(format: "universe == %@", "Star Wars"))
    

    除了==之外,我们还可以使用诸如<>之类的比较来过滤对象。例如,这将返回Defiant,Enterprise和Executor:

    NSPredicate(format: "name < %@", "F")) var ships: FetchedResults<Ship>
    

    %@在后台做了很多工作,尤其是在将本机Swift类型转换为等效的Core Data时。例如,我们可以使用IN谓词来检查 universe 是否是数组中三个选项之一,如下所示:

    NSPredicate(format: "universe IN %@", ["Aliens", "Firefly", "Star Trek"])
    

    我们还可以使用谓词来检查字符串的一部分,例如使用BEGINSWITHCONTAINS这样的运算符。例如,这将返回所有以大写字母E开头的船:

    NSPredicate(format: "name BEGINSWITH %@", "E"))
    

    该谓词区分大小写;如果要忽略大小写,则需要对此进行修改:

    NSPredicate(format: "name BEGINSWITH[c] %@", "e"))
    

    CONTAINS[c]的工作方式类似,除了可以从子字符串开始,它可以位于属性内的任何位置。

    最后,您可以使用NOT翻转谓词,以获得其常规行为的反函数。例如,这将查找所有以E开头的船舶:

    NSPredicate(format: "NOT name BEGINSWITH[c] %@", "e"))
    

    如果您需要更复杂的谓词,请使用AND将它们连接起来以建立所需的尽可能多的精度,或者为Core Data添加导入并查看NSCompoundPredicate——它使您可以从多个较小的谓词中构建一个谓词。

    译自 Filtering @FetchRequest using NSPredicate

    相关文章

      网友评论

        本文标题:SwiftUI Core Data:使用 NSPredicate

        本文链接:https://www.haomeiwen.com/subject/uirgahtx.html