PredicateFlow 1.6

PredicateFlow 1.6

Andrea Del Fante维护。



  • 作者
  • andreadelfante

PredicateFlow

Build Status CocoaPods Compatible Platform contributions welcome License

编写令人惊叹的、强类型且易于阅读的NSPredicate。这个库允许你编写可流动的NSPredicate,而无需猜测属性名称、谓词操作或编写错误的参数类型。

支持的平台

  • iOS 9.0+
  • macOS 10.9+
  • tvOS 9.0+
  • watchOS 2.0+

安装

CocoaPods实际上是安装它的唯一方式。

Cocoapods

需要CocoaPods 0.39.0+版本来编译此库

  1. 在你的Podfile中添加pod 'PredicateFlow'并运行pod install

  2. 在Xcode中,点击文件列表中的你的项目,选择TARGETS下的目标,点击Build Phases标签,然后点击左上角的加号创建一个新的Run Script阶段

  3. 将新的Run Script阶段拖到Compile Sources阶段之上和Check Pods Manifest.lock之下,展开并粘贴以下脚本

    "$PODS_ROOT/Sourcery/bin/sourcery" --sources "$PODS_ROOT/PredicateFlow/PredicateFlow/Classes/Utils/" --sources "$SRCROOT" --templates "$PODS_ROOT/PredicateFlow/PredicateFlow/Templates/PredicateFlow.stencil" --output "$SRCROOT/PredicateFlow.generated.swift"
    

    如果您正在使用 PredicateFlow-Realm,请替换上面的脚本为以下脚本

    "$PODS_ROOT/Sourcery/bin/sourcery" --sources "$PODS_ROOT/PredicateFlow/PredicateFlow/Classes/Utils/" --sources "$SRCROOT"  --sources "$PODS_ROOT/RealmSwift" --templates "$PODS_ROOT/PredicateFlow/PredicateFlow/Templates/PredicateFlow-Realm.stencil" --output "$SRCROOT/PredicateFlow.generated.swift"
    

    仅限 Xcode 10,添加一个新的 输出文件 并粘贴以下内容

    $SRCROOT/PredicateFlow.generated.swift
    
  4. 构建您的项目。在 Finder 中,您现在将在 $SRCROOT 文件夹中看到一个 PredicateFlow.generated.swift 文件,将 PredicateFlow.generated.swift 文件拖入您的项目中,并取消勾选 如果需要则复制项目

提示:*.generated.swift 模式添加到您的 .gitignore 文件中,以防止不必要的冲突。

用法

定义一个具有自身属性的类/结构体,实现 PredicateSchema

import PredicateFlow

class Dog: PredicateSchema {
	
	private var name: String = ""
	private var age: Int = 0
	private var isHungry: Bool = false
	private var owner: Person?
}

class Person: PredicateSchema {
	
	enum Sex {
		case male
		case female
	}
	
	private var name: String = ""
	private var birth: Date?
	private var sex: Sex!
	private var dogs: [Dog] = []
}

构建项目。PredicateFlow 将自动生成属性引用以构建谓词,并将它们放在结构体中。

// Generated using Sourcery 0.10.0 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT


import PredicateFlow

/// The "Dog" Predicate Schema
internal struct DogSchema: GeneratedPredicateSchema {
    private var compoundFieldBuilder: CompoundFieldBuilder

    /// DO NOT USE THIS INIT DIRECTLY!
    internal init(compoundFieldBuilder: CompoundFieldBuilder) {
        self.compoundFieldBuilder = compoundFieldBuilder
    }

    /// "name" property
    internal var name: StringPredicateProperty { return builder.string("name") }
    /// "name" property for static access
    internal static var name: StringPredicateProperty { return DogSchema().name }
    
    // Other properties of Dog class autogenerated...
}
/// The "Person" Predicate Schema
internal struct PersonSchema: GeneratedPredicateSchema {
    private var compoundFieldBuilder: CompoundFieldBuilder

    /// DO NOT USE THIS INIT DIRECTLY!
    internal init(compoundFieldBuilder: CompoundFieldBuilder) {
        self.compoundFieldBuilder = compoundFieldBuilder
    }

    /// "name" property
    internal var name: StringPredicateProperty { return builder.string("name") }
    /// "name" property for static access
    internal static var name: StringPredicateProperty { return PersonSchema().name }
    
    // Other properties of Person class autogenerated...
}

要编写可流畅的 NSPredicate,只需写下

DogSchema.age.isEqual(10).query()
// or
// Vanilla mode: 
// NSPredicate("age == %@", 10)

您也可以编写复合谓词,并使用深层字段

PredicateBuilder(DogSchema.age > 10)
    .and(DogSchema.isHungry.isTrue)
    .and(DogSchema.age.between(1, 10))
    .and(DogSchema.owner.element().name == "Foo")
    .or(DogSchema.owner.element().dogs.maxElements().age > 10)
    .or(DogSchema.owner.element().dogs.anyElements().name == "Foo")
    .build()
    
// Vanilla mode: 
// NSPredicate("age > %@ AND isHungry == %@ AND age BETWEEN %@ AND owner.name == %@ OR [email protected] > %@ OR ANY owner.dogs.name == %@", 10, true, [1, 10], "Foo", 10, "Foo")

PredicateFlow 还可以构建 KeyPaths,您可以将其用作强类型之一。

DogSchema.age.keyPath()
DogSchema.owner.element().dogs.keyPath()

// Vanilla mode:
// "age"
// "owner.dogs"

PredicateFlow/Realm

如果您想在 Realm 中使用可流畅的和强类型的查询,请在您的 Podfile 中添加 两者 pod 'PredicateFlow'pod 'PredicateFlow/Realm',然后运行 pod install

let realm = try! Realm()
realm.objects(Dog.self)
    .filter(DogSchema.age.isGreater(than: 10))
    .filter(DogSchema.isHungry.isTrue)
    .sorted(DogSchema.age.ascending())
    
// Vanilla mode:
realm.objects(Dog.self)
    .filter("age > %@", 10)
    .filter("isHungry == %@", true)
    .sorted("age", ascending: true)

贡献

PredicateFlow 是一个开源项目,因此欢迎贡献。您可以为问题或建议创建问题,并且您可以通过打开一个带有更改的 pull request 提议您自己的修复。

许可证

PredicateFlow 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。

致谢

此库由 Sourcery 支持。

作者

Andrea Del Fante, [email protected]