A GUI for dynamically creating NSPredicates at runtime to query data in your iOS app.

Overview

PredicateEditor

PredicateEditor is a visual editor for creating and using NSPredicates for querying data in your app.

Screenshot

PredicateEditor was inspired by the implementation in Workflow

Features

  • Create filters for the following property types: Strings, NSDates, NSNumbers, Ints, Floats, and Bools.
  • Easily define the properties & keyPaths you'd like to be able to filter on.
  • Filters can be added & deleted at will in the UI - The user can define as many filters as required.
  • Input types are automatically updated to reflect the property type - Strings, Dates, Numbers etc
  • Supports multiple sections of filters, each with its own compound predicate - AND or OR. Sections can again be clubbed together with other compound predicates.

Installation

PredicateEditor is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "PredicateEditor"

Requirements

  • Requires Xcode 7.3 with Swift 2.2
  • Deployment target of iOS 9+ (due to liberal use of UIStackViews)

Please note that it's not possible to use this library in Obj-C code yet

Usage

Creating the editor

The first step in using the PredicateEditor is to create sections with the keyPaths you'd like to be made available for filtering.

Sections are created using one or more KeyPathDescriptors. Each of these describe the property that is to be filtered on, and the keyPath to use while filtering.

In most cases, each section would correspond to a particular model in your app.

var keyPaths: [KeyPathDescriptor] = []

//Assuming you have a Person model with properties `name`, `age`, `dateOfBirth` & a Bool `isDeveloper`, create a descriptor for each of them.
let kp1 = KeyPathDescriptor(keyPath:"name", title: "Name", propertyType: .String)
let kp2 = KeyPathDescriptor(keyPath:"dateOfBirth", title: "Date Of Birth", propertyType: .Date)
let kp3 = KeyPathDescriptor(keyPath:"age", title: "Age", propertyType: .Int)
let kp4 = KeyPathDescriptor(keyPath:"isDeveloper", title: "Is a Developer", propertyType: .Boolean)
keyPaths = [kp1, kp2, kp3, kp4]

let section = Section(title: "Filter People", keyPaths: keyPaths)

Now you can create a PredicateEditor View Controller instance, and present it:

let predicateEditorVC = PredicateEditorViewController(sections: [section])
predicateEditorVC.delegate = self // Conform to PredicateEditorDelegate to receive callbacks.

// Wrap the editor in a nav controller in order to be able to dismiss it.
let nc = UINavigationController(rootViewController: predicateEditorVC)
nc.modalTransitionStyle = .CoverVertical
presentViewController(nc, animated: true, completion: nil)

Enumeration Options

Suppose the values of a particular property can be listed as an enumeration, and you'd like the user to be able to specify a value only from any of those options, you can additionally configure the descriptor:

let kp = KeyPathDescriptor(keyPath:"gender", title: "Gender", propertyType: .String)
kp.enumerationOptions = ["Male", "Female"]

Editor Configuration

Additionally create and pass a PredicatedEditorConfig object to the predicate editor during init.

var config = PredicatorEditorConfig()
config.backgroundColor = UIColor(white: 0.9, alpha: 1)
config.sectionBackgroundColor = UIColor(white: 0.95, alpha: 1)
...

let predicateEditor = PredicateEditorViewController(sections: [section], config: config)

Pre-defined Sections

By default, sections start out empty, and the user has to manually create new filters. However, if you'd like to present a pre-defined set of filters to the user, you can do so by creating and adding Rows to the section.

// For each filter you'd like to pre-define, create a Row with the descriptor, comparisonType and value.

let descriptor = KeyPathDescriptor(keyPath: "name", title: "Name", propertyType: KeyPathPropertyType.String)
let comparisonType: KeyPathComparisonType = .Contains
let value = "John"
if let row = Row(descriptor: descriptor, comparisonType: comparisonType, value: value){
  section.append(row)
}

let descriptor2 = KeyPathDescriptor(keyPath: "dob", title: "Date of Birth", propertyType: KeyPathPropertyType.Date)
let comparisonType2: KeyPathComparisonType = .IsAfter
let value2 = NSDate(timeIntervalSince1970: 321312311)
if let row2 = Row(descriptor: descriptor2, comparisonType: comparisonType2, value: value2){
  section.append(row2)
}

Note that the comparisonType & value have to be compatible with the descriptor's property type. For example, you should not create a filter with IsGreaterThan comparison, on a String property type. Doing so will lead to an exception being thrown when creating the predicate.

Obtaining Predicates

Once the user finishes work in the predicate editor, and taps the done button, predicateEditorDidFinishWithPredicates: is called on the delegate object, along with an array of NSPredicates - one for each section.

It's up to you to use these predicates any way you want - for instance, you can combine all of them into one compound predicate and filter a single model, or use each predicate on a separate model. In the example above, the resulting predicate would be used on the Person model.

let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
let filteredPeople = (people as NSArray).filteredArrayUsingPredicate(compoundPredicate) as! [Person]

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Todo:

  • Add an In-Between comparison type.
  • Add more configuration options.
  • Add support for filtering array property types.

Author

Arvindh Sukumar (Github)

License

PredicateEditor is available under the MIT license. See the LICENSE file for more info.

You might also like...
Realm is a mobile database: a replacement for Core Data & SQLite

Realm is a mobile database that runs directly inside phones, tablets or wearables. This repository holds the source code for the iOS, macOS, tvOS & wa

A library that provides the ability to import/export Realm files from a variety of data container formats.

Realm Converter Realm Converter is an open source software utility framework to make it easier to get data both in and out of Realm. It has been built

An alternative to Core Data for people who like having direct SQL access.

FCModel 2 An alternative to Core Data for people who like having direct SQL access. By Marco Arment. See the LICENSE file for license info (it's the M

Synco - Synco uses Firebase's Realtime Database to synchronize data across multiple devices, in real time

Synco Synco uses Firebase's Realtime Database to synchronize a color across mult

CoreDataCloudKitShare - Learn how to use Core Data CloudKit

Sharing Core Data Objects Between iCloud Users Implement the flow to share data

BowTies - The main purpose of this application is to show how you can perform simple operations using Core Data
BowTies - The main purpose of this application is to show how you can perform simple operations using Core Data

BowTies The main purpose of this application is to show how you can perform simp

Data Scanner Demo

DataScannerDemo Hi there thanks for visiting this repo. If you like it I encourage you to please leave a like. Before Before iOS 16 it was quite unint

Realm-powered Core Data persistent store
Realm-powered Core Data persistent store

RealmIncrementalStore Realm-powered Core Data persistent store Wait, what? I like Realm. Realm's memory-mapped DB blows other databases out of the wat

This project has been developed to understand GraphQL and Diffable Data Source. Created on 20.06.2022.

SpaceX Launches First in first. You need to build all packages before building the project. Packages: Extensions API Open Extensions folder under proj

Comments
  • PredicateEditor in Objective C

    PredicateEditor in Objective C

    Hello dear,

    First of all, thank you for your awesome project, that's really easily to create and manage forms and predicate.

    Unfortunately, i would like to use your project in an Objective C project.

    The problem come from the struct "KeyPathDescriptor" that I'm not able to use in my Objective C class.

    Do you have a workaround or will you create an Objective C alternative ?

    Thank you in advance for your answer,

    Best regards

    opened by AsKaeternam 1
  • update to swift 3 possible?

    update to swift 3 possible?

    Hi, I would love to test and maybe use the PredicateEditor for iOS because I did not found anything cool like this for iOS/Swift. Sadly I do get some issues with podfiles and required versions for SnapKit. Could you please update dependencies for Swift 3. so to SnapKit 3.0.2 Thanks in advance.

    opened by iORichy 0
Releases(0.9.1)
Owner
Arvindh Sukumar
Arvindh Sukumar
URL query encoder with OpenAPI serialization options support

URLQueryEncoder A customizable Swift Encoder that encodes instances of data type

Alexander Grebenyuk 31 Nov 30, 2022
rTracker is a complete iOS application for creating local on-device databases ('trackers') to log data with timestamps.

rTracker is a complete iOS application for creating local on-device databases ('trackers') to log data with timestamps. Trackers can use a va

Rob Miller 40 Dec 10, 2022
Creating a Todo app using Realm and SwiftUI

Realmで作るTodoアプリ note記事「【SwiftUI】Realmを使ってTodoアプリを作る」のソースです。

null 1 Jul 20, 2022
CloudKit, Apple’s remote data storage service, provides a possibility to store app data using users’ iCloud accounts as a back-end storage service.

CloudKit, Apple’s remote data storage service, provides a possibility to store app data using users’ iCloud accounts as a back-end storage service. He

Yalantis 252 Nov 4, 2022
Your Data Storage Troubleshooter 🛠

Your Data Storage Troubleshooter ?? Introduction StorageKit is a framework which reduces the complexity of managing a persistent layer. You can easily

StorageKit 231 Dec 29, 2022
PJAlertView - This library is to make your own custom alert views to match your apps look and feel

PJAlertView - This library is to make your own custom alert views to match your apps look and feel

prajeet 6 Nov 10, 2017
Check your Valorant store from your phone!

Valorant Store Checker Description VSC (Valorant Store Tracker) is an open source iOS app that allows you to track your store and preview your skins.

Gordon 20 Dec 29, 2022
Disk is a powerful and simple file management library built with Apple's iOS Data Storage Guidelines in mind

Disk is a powerful and simple file management library built with Apple's iOS Data Storage Guidelines in mind

Saoud Rizwan 3k Jan 3, 2023
🛶Shallows is a generic abstraction layer over lightweight data storage and persistence.

Shallows Shallows is a generic abstraction layer over lightweight data storage and persistence. It provides a Storage<Key, Value> type, instances of w

Oleg Dreyman 620 Dec 3, 2022
KeyPathKit is a library that provides the standard functions to manipulate data along with a call-syntax that relies on typed keypaths to make the call sites as short and clean as possible.

KeyPathKit Context Swift 4 has introduced a new type called KeyPath, with allows to access the properties of an object with a very nice syntax. For in

Vincent Pradeilles 406 Dec 25, 2022