├── PredicateEditor ├── Assets │ ├── .gitkeep │ └── Images.xcassets │ │ ├── Contents.json │ │ └── delete.imageset │ │ ├── noun_minus_81452.png │ │ ├── noun_minus_81452@2x.png │ │ ├── noun_minus_81452@3x.png │ │ └── Contents.json └── Classes │ ├── .gitkeep │ ├── Extensions.swift │ ├── ErrorToastView.swift │ ├── PredicateComparable.swift │ ├── SemiModalTransition.swift │ ├── Section.swift │ ├── DatePickerViewController.swift │ ├── KeyPathDescriptor.swift │ ├── PredicateEditorViewController.swift │ └── Row.swift ├── Example ├── .idea │ ├── .name │ ├── xcode.xml │ ├── modules.xml │ ├── misc.xml │ └── runConfigurations │ │ └── PredicateEditor_Example.xml ├── Pods │ ├── Target Support Files │ │ ├── SnapKit │ │ │ ├── SnapKit-prefix.pch │ │ │ ├── SnapKit.modulemap │ │ │ ├── SnapKit-dummy.m │ │ │ ├── SnapKit-umbrella.h │ │ │ ├── SnapKit.xcconfig │ │ │ └── Info.plist │ │ ├── Timepiece │ │ │ ├── Timepiece-prefix.pch │ │ │ ├── Timepiece.modulemap │ │ │ ├── Timepiece-dummy.m │ │ │ ├── Timepiece-umbrella.h │ │ │ ├── Timepiece.xcconfig │ │ │ └── Info.plist │ │ ├── PredicateEditor │ │ │ ├── PredicateEditor-prefix.pch │ │ │ ├── PredicateEditor.modulemap │ │ │ ├── PredicateEditor-dummy.m │ │ │ ├── PredicateEditor-umbrella.h │ │ │ ├── PredicateEditor.xcconfig │ │ │ ├── ResourceBundle-PredicateEditor-Info.plist │ │ │ └── Info.plist │ │ ├── SeedStackViewController │ │ │ ├── SeedStackViewController-prefix.pch │ │ │ ├── SeedStackViewController.modulemap │ │ │ ├── SeedStackViewController-dummy.m │ │ │ ├── SeedStackViewController-umbrella.h │ │ │ ├── SeedStackViewController.xcconfig │ │ │ └── Info.plist │ │ ├── Pods-PredicateEditor_Tests │ │ │ ├── Pods-PredicateEditor_Tests-acknowledgements.markdown │ │ │ ├── Pods-PredicateEditor_Tests.modulemap │ │ │ ├── Pods-PredicateEditor_Tests-dummy.m │ │ │ ├── Pods-PredicateEditor_Tests-umbrella.h │ │ │ ├── Pods-PredicateEditor_Tests.debug.xcconfig │ │ │ ├── Pods-PredicateEditor_Tests.release.xcconfig │ │ │ ├── Info.plist │ │ │ ├── Pods-PredicateEditor_Tests-acknowledgements.plist │ │ │ ├── Pods-PredicateEditor_Tests-frameworks.sh │ │ │ └── Pods-PredicateEditor_Tests-resources.sh │ │ └── Pods-PredicateEditor_Example │ │ │ ├── Pods-PredicateEditor_Example.modulemap │ │ │ ├── Pods-PredicateEditor_Example-dummy.m │ │ │ ├── Pods-PredicateEditor_Example-umbrella.h │ │ │ ├── Info.plist │ │ │ ├── Pods-PredicateEditor_Example.debug.xcconfig │ │ │ ├── Pods-PredicateEditor_Example.release.xcconfig │ │ │ ├── Pods-PredicateEditor_Example-frameworks.sh │ │ │ ├── Pods-PredicateEditor_Example-acknowledgements.markdown │ │ │ ├── Pods-PredicateEditor_Example-resources.sh │ │ │ └── Pods-PredicateEditor_Example-acknowledgements.plist │ ├── SeedStackViewController │ │ ├── StackViewController │ │ │ ├── UIStackViewExtensions.swift │ │ │ ├── StackViewController.h │ │ │ ├── Info.plist │ │ │ ├── UIViewExtensions.swift │ │ │ ├── StackViewItem.swift │ │ │ ├── SeparatorView.swift │ │ │ ├── StackViewController.swift │ │ │ └── AutoScrollView.swift │ │ ├── LICENSE.md │ │ └── README.md │ ├── Timepiece │ │ ├── Sources │ │ │ ├── String+Timepiece.swift │ │ │ ├── NSCalendar+Timepiece.swift │ │ │ ├── NSDateComponents+Timepiece.swift │ │ │ ├── Int+Timepiece.swift │ │ │ ├── Duration.swift │ │ │ ├── NSTimeInterval+Timepiece.swift │ │ │ ├── NSCalendarUnit+Timepiece.swift │ │ │ └── NSDate+Timepiece.swift │ │ ├── LICENSE │ │ └── README.md │ ├── Manifest.lock │ ├── Local Podspecs │ │ └── PredicateEditor.podspec.json │ └── SnapKit │ │ ├── LICENSE │ │ ├── README.md │ │ └── Source │ │ ├── SnapKit.swift │ │ ├── ConstraintRelation.swift │ │ ├── EdgeInsets.swift │ │ ├── ViewController+SnapKit.swift │ │ ├── LayoutConstraint.swift │ │ ├── ConstraintItem.swift │ │ ├── Debugging.swift │ │ ├── ConstraintAttributes.swift │ │ └── View+SnapKit.swift ├── Podfile ├── PredicateEditor │ ├── Playground.playground │ │ ├── contents.xcplayground │ │ └── Contents.swift │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Person.swift │ ├── Info.plist │ ├── PersonTableViewCell.swift │ ├── AppDelegate.swift │ └── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard ├── PredicateEditor.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── PredicateEditor-Example.xcscheme ├── PredicateEditor.xcworkspace │ └── contents.xcworkspacedata ├── Podfile.lock └── Tests │ ├── Info.plist │ └── Tests.swift ├── _Pods.xcodeproj ├── PredicateEditor.playground ├── contents.xcplayground ├── playground.xcworkspace │ └── contents.xcworkspacedata └── Contents.swift ├── .travis.yml ├── .gitignore ├── LICENSE ├── PredicateEditor.podspec └── README.md /PredicateEditor/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Example/.idea/.name: -------------------------------------------------------------------------------- 1 | PredicateEditor -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Timepiece-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /PredicateEditor/Assets/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/PredicateEditor-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/SeedStackViewController-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit.modulemap: -------------------------------------------------------------------------------- 1 | framework module SnapKit { 2 | umbrella header "SnapKit-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SnapKit : NSObject 3 | @end 4 | @implementation PodsDummy_SnapKit 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Timepiece.modulemap: -------------------------------------------------------------------------------- 1 | framework module Timepiece { 2 | umbrella header "Timepiece-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Timepiece-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Timepiece : NSObject 3 | @end 4 | @implementation PodsDummy_Timepiece 5 | @end 6 | -------------------------------------------------------------------------------- /PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvindhsukumar/PredicateEditor/HEAD/PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452.png -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/PredicateEditor.modulemap: -------------------------------------------------------------------------------- 1 | framework module PredicateEditor { 2 | umbrella header "PredicateEditor-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double SnapKitVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char SnapKitVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvindhsukumar/PredicateEditor/HEAD/PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452@2x.png -------------------------------------------------------------------------------- /PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvindhsukumar/PredicateEditor/HEAD/PredicateEditor/Assets/Images.xcassets/delete.imageset/noun_minus_81452@3x.png -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/PredicateEditor-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_PredicateEditor : NSObject 3 | @end 4 | @implementation PodsDummy_PredicateEditor 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Timepiece-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double TimepieceVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char TimepieceVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /PredicateEditor.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Example/.idea/xcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /PredicateEditor.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'PredicateEditor_Example' do 4 | pod 'PredicateEditor', :path => '../' 5 | 6 | target 'PredicateEditor_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/SeedStackViewController.modulemap: -------------------------------------------------------------------------------- 1 | framework module StackViewController { 2 | umbrella header "SeedStackViewController-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Playground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/PredicateEditor-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double PredicateEditorVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char PredicateEditorVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_PredicateEditor_Tests { 2 | umbrella header "Pods-PredicateEditor_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/SeedStackViewController-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SeedStackViewController : NSObject 3 | @end 4 | @implementation PodsDummy_SeedStackViewController 5 | @end 6 | -------------------------------------------------------------------------------- /PredicateEditor.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | var str = "Hello, playground" 6 | 7 | let vc = UIViewController() 8 | vc.view.backgroundColor = UIColor.blueColor() 9 | vc.view.frame -------------------------------------------------------------------------------- /Example/PredicateEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_PredicateEditor_Example { 2 | umbrella header "Pods-PredicateEditor_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_PredicateEditor_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_PredicateEditor_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_PredicateEditor_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_PredicateEditor_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_PredicateEditor_TestsVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_PredicateEditor_TestsVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_PredicateEditor_ExampleVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_PredicateEditor_ExampleVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/SeedStackViewController-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "StackViewController.h" 4 | 5 | FOUNDATION_EXPORT double StackViewControllerVersionNumber; 6 | FOUNDATION_EXPORT const unsigned char StackViewControllerVersionString[]; 7 | 8 | -------------------------------------------------------------------------------- /Example/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/PredicateEditor.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/UIStackViewExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIStackViewExtensions.swift 3 | // StackViewController 4 | // 5 | // Created by Indragie Karunaratne on 2016-04-24. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIStackView { 12 | public func removeAllArrangedSubviews() { 13 | arrangedSubviews.forEach { 14 | $0.removeFromSuperview() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/String+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Naoto Kaneko on 2015/03/01. 6 | // Copyright (c) 2015年 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension String { 12 | // MARK - Parse into NSDate 13 | 14 | func dateFromFormat(format: String) -> NSDate? { 15 | let formatter = NSDateFormatter() 16 | formatter.dateFormat = format 17 | return formatter.dateFromString(self) 18 | } 19 | } -------------------------------------------------------------------------------- /PredicateEditor/Assets/Images.xcassets/delete.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "noun_minus_81452.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "noun_minus_81452@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "noun_minus_81452@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/SnapKit.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SnapKit 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Timepiece.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Timepiece 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -workspace Example/PredicateEditor.xcworkspace -scheme PredicateEditor-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/SeedStackViewController.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_LDFLAGS = -framework "UIKit" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/StackViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // StackViewController.h 3 | // StackViewController 4 | // 5 | // Created by Indragie Karunaratne on 2016-04-16. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for StackViewController. 12 | FOUNDATION_EXPORT double StackViewControllerVersionNumber; 13 | 14 | //! Project version string for StackViewController. 15 | FOUNDATION_EXPORT const unsigned char StackViewControllerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PredicateEditor (0.1.0): 3 | - SeedStackViewController (~> 0.2) 4 | - SnapKit (~> 0.21) 5 | - Timepiece (~> 0.4) 6 | - SeedStackViewController (0.2.1) 7 | - SnapKit (0.21.1) 8 | - Timepiece (0.4.3) 9 | 10 | DEPENDENCIES: 11 | - PredicateEditor (from `../`) 12 | 13 | EXTERNAL SOURCES: 14 | PredicateEditor: 15 | :path: "../" 16 | 17 | SPEC CHECKSUMS: 18 | PredicateEditor: 36c394b4a3c5dd9168131f8d8bf4f4627162d776 19 | SeedStackViewController: aece175e207147f58b2ca9c502ab2bd26eb00952 20 | SnapKit: bbad04cb016c7cead63965f16b00c09318d271ee 21 | Timepiece: b5038887b91d6eb70653173f4270e06b3abeac41 22 | 23 | PODFILE CHECKSUM: 497240e87c1b562f70d58ab4ea4a96607eff5fc2 24 | 25 | COCOAPODS: 1.0.1 26 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - PredicateEditor (0.1.0): 3 | - SeedStackViewController (~> 0.2) 4 | - SnapKit (~> 0.21) 5 | - Timepiece (~> 0.4) 6 | - SeedStackViewController (0.2.1) 7 | - SnapKit (0.21.1) 8 | - Timepiece (0.4.3) 9 | 10 | DEPENDENCIES: 11 | - PredicateEditor (from `../`) 12 | 13 | EXTERNAL SOURCES: 14 | PredicateEditor: 15 | :path: "../" 16 | 17 | SPEC CHECKSUMS: 18 | PredicateEditor: 36c394b4a3c5dd9168131f8d8bf4f4627162d776 19 | SeedStackViewController: aece175e207147f58b2ca9c502ab2bd26eb00952 20 | SnapKit: bbad04cb016c7cead63965f16b00c09318d271ee 21 | Timepiece: b5038887b91d6eb70653173f4270e06b3abeac41 22 | 23 | PODFILE CHECKSUM: 497240e87c1b562f70d58ab4ea4a96607eff5fc2 24 | 25 | COCOAPODS: 1.0.1 26 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/PredicateEditor.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/PredicateEditor 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController" "$PODS_CONFIGURATION_BUILD_DIR/SnapKit" "$PODS_CONFIGURATION_BUILD_DIR/Timepiece" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /Example/.idea/runConfigurations/PredicateEditor_Example.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | import PredicateEditor 4 | 5 | class Tests: XCTestCase { 6 | 7 | override func setUp() { 8 | super.setUp() 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDown() { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | super.tearDown() 15 | } 16 | 17 | func testExample() { 18 | // This is an example of a functional test case. 19 | XCTAssert(true, "Pass") 20 | } 21 | 22 | func testPerformanceExample() { 23 | // This is an example of a performance test case. 24 | self.measureBlock() { 25 | // Put the code you want to measure the time of here. 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/ResourceBundle-PredicateEditor-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 0.1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/NSCalendar+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSCalendar+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Mattijs on 25/04/15. 6 | // Copyright (c) 2015 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | private let supportsDateByAddingUnit = NSCalendar.currentCalendar().respondsToSelector(#selector(NSCalendar.dateByAddingUnit(_:value:toDate:options:))) 12 | 13 | extension NSCalendar { 14 | func dateByAddingDuration(duration: Duration, toDate date: NSDate, options opts: NSCalendarOptions) -> NSDate? { 15 | if supportsDateByAddingUnit { 16 | return dateByAddingUnit(duration.unit, value: duration.value, toDate: date, options: .SearchBackwards)! 17 | } 18 | else { 19 | // otherwise fallback to NSDateComponents 20 | return dateByAddingComponents(NSDateComponents(duration), toDate: date, options: .SearchBackwards)! 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | Example/PredicateEditor/Playground.playground 5 | PredicateEditor.playground 6 | 7 | Example/PredicateEditor/Playground.playground/Contents.swift 8 | PredicateEditor.playground/Contents.swift 9 | 10 | # Xcode 11 | build/ 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | *.xccheckout 22 | profile 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | 28 | # Bundler 29 | .bundle 30 | 31 | Carthage 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 35 | # 36 | # Note: if you ignore the Pods directory, make sure to uncomment 37 | # `pod install` in .travis.yml 38 | # 39 | # Pods/ 40 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SnapKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.21.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Timepiece/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.4.3 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 15/07/16. 6 | // 7 | // 8 | 9 | import Foundation 10 | import Timepiece 11 | 12 | extension Dictionary { 13 | func keysToArray() -> [Key] { 14 | return Array(self.keys) 15 | } 16 | 17 | func valuesToArray() -> [Value] { 18 | return Array(self.values) 19 | } 20 | } 21 | 22 | extension NSDate { 23 | var time: NSDate { 24 | return change(year: 0, month: 0, day: 0, hour: hour, minute: minute, second: second) 25 | } 26 | } 27 | 28 | extension Bool { 29 | func toString() -> String { 30 | return self ? "true" : "false" 31 | } 32 | 33 | static func fromString(string: String) -> Bool { 34 | return string == "true" ? true : false 35 | } 36 | } 37 | 38 | extension NSPredicate { 39 | var isEmpty: Bool { 40 | return predicateFormat == "FALSEPREDICATE" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor" "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController" "$PODS_CONFIGURATION_BUILD_DIR/SnapKit" "$PODS_CONFIGURATION_BUILD_DIR/Timepiece" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor/PredicateEditor.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController/StackViewController.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SnapKit/SnapKit.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Timepiece/Timepiece.framework/Headers" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT}/Pods 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/PredicateEditor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor" "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController" "$PODS_CONFIGURATION_BUILD_DIR/SnapKit" "$PODS_CONFIGURATION_BUILD_DIR/Timepiece" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor/PredicateEditor.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController/StackViewController.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SnapKit/SnapKit.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Timepiece/Timepiece.framework/Headers" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT}/Pods 8 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SeedStackViewController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.2.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/UIViewExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewExtensions.swift 3 | // StackViewController 4 | // 5 | // Created by Indragie Karunaratne on 2016-04-24. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | public func activateSuperviewHuggingConstraints(insets insets: UIEdgeInsets = UIEdgeInsetsZero) -> [NSLayoutConstraint] { 13 | translatesAutoresizingMaskIntoConstraints = false 14 | let views = ["view": self] 15 | let metrics = ["top": insets.top, "left": insets.left, "bottom": insets.bottom, "right": insets.right] 16 | var constraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-left-[view]-right-|", options: [], metrics: metrics, views: views) 17 | constraints.appendContentsOf(NSLayoutConstraint.constraintsWithVisualFormat("V:|-top-[view]-bottom-|", options: [], metrics: metrics, views: views)) 18 | NSLayoutConstraint.activateConstraints(constraints) 19 | return constraints 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/PredicateEditor.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PredicateEditor", 3 | "version": "0.1.0", 4 | "summary": "A short description of PredicateEditor.", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com//PredicateEditor", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "Arvindh Sukumar": "arvindh.sukumar@gmail.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com//PredicateEditor.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "9.0" 20 | }, 21 | "source_files": "PredicateEditor/Classes/**/*", 22 | "resource_bundles": { 23 | "PredicateEditor": [ 24 | "PredicateEditor/Assets/*.png", 25 | "PredicateEditor/Assets/*.xcassets" 26 | ] 27 | }, 28 | "dependencies": { 29 | "SnapKit": [ 30 | "~> 0.21" 31 | ], 32 | "SeedStackViewController": [ 33 | "~> 0.2" 34 | ], 35 | "Timepiece": [ 36 | "~> 0.4" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Arvindh Sukumar 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2016 Seed Platform, Inc.** 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/StackViewItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewControllerConvertible.swift 3 | // Seed 4 | // 5 | // Created by Indragie Karunaratne on 1/29/16. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol StackViewItem: AnyObject { 12 | func toViewController() -> UIViewController 13 | } 14 | 15 | extension UIViewController: StackViewItem { 16 | public func toViewController() -> UIViewController { 17 | return self 18 | } 19 | } 20 | 21 | extension UIView: StackViewItem { 22 | public func toViewController() -> UIViewController { 23 | return WrapperViewController(view: self) 24 | } 25 | } 26 | 27 | private class WrapperViewController: UIViewController { 28 | private let _view: UIView 29 | 30 | init(view: UIView) { 31 | _view = view 32 | super.init(nibName: nil, bundle: nil) 33 | } 34 | 35 | required init?(coder aDecoder: NSCoder) { 36 | fatalError("init(coder:) has not been implemented") 37 | } 38 | 39 | private override func loadView() { 40 | view = _view 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Naoto Kaneko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Person.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Person.swift 3 | // PredicateEditor 4 | // 5 | // Created by Arvindh Sukumar on 24/07/16. 6 | // Copyright © 2016 CocoaPods. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Person: NSObject { 12 | var name: String! 13 | var age: Int { 14 | return NSDate().year - dateOfBirth.year 15 | } 16 | var dateOfBirth: NSDate! 17 | var appointmentTime: NSDate { 18 | return appointmentDate 19 | } 20 | var appointmentDate: NSDate! 21 | var favoriteColor: String! 22 | var gender: String! 23 | var isADeveloper: Bool = false 24 | var heightInCentimeters: Float = 0 25 | 26 | init(name: String, dateOfBirth:NSDate, appointmentDate: NSDate, favoriteColor: String, gender: String, isADeveloper: Bool, heightInCentimeters: Float){ 27 | super.init() 28 | self.name = name 29 | self.dateOfBirth = dateOfBirth 30 | self.appointmentDate = appointmentDate 31 | self.favoriteColor = favoriteColor 32 | self.gender = gender 33 | self.isADeveloper = isADeveloper 34 | self.heightInCentimeters = heightInCentimeters 35 | } 36 | } -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor" "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController" "$PODS_CONFIGURATION_BUILD_DIR/SnapKit" "$PODS_CONFIGURATION_BUILD_DIR/Timepiece" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor/PredicateEditor.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController/StackViewController.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SnapKit/SnapKit.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Timepiece/Timepiece.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "PredicateEditor" -framework "SnapKit" -framework "StackViewController" -framework "Timepiece" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | SnapKit is a DSL to make Auto Layout easy on both iOS and OS X. 4 | 5 | [![Build Status](https://travis-ci.org/SnapKit/SnapKit.svg)](https://travis-ci.org/SnapKit/SnapKit) 6 | [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/SnapKit.svg)](https://img.shields.io/cocoapods/v/SnapKit.svg) 7 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 8 | 9 | ```swift 10 | import SnapKit 11 | 12 | class MyViewController: UIViewController { 13 | 14 | lazy var box = UIView() 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | self.view.addSubview(box) 20 | box.snp_makeConstraints { make in 21 | make.width.height.equalTo(50) 22 | make.center.equalTo(self.view) 23 | } 24 | } 25 | 26 | } 27 | ``` 28 | 29 | ## Resources 30 | 31 | * [Documentation](http://snapkit.io/docs/) 32 | * [F.A.Q.](http://snapkit.io/faq/) 33 | * [Legacy Platforms (iOS 7.0, OS X 10.9)](http://snapkit.io/legacy-platforms/) 34 | 35 | ## License 36 | 37 | MIT license. See the `LICENSE` file for details. 38 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor" "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController" "$PODS_CONFIGURATION_BUILD_DIR/SnapKit" "$PODS_CONFIGURATION_BUILD_DIR/Timepiece" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/PredicateEditor/PredicateEditor.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SeedStackViewController/StackViewController.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/SnapKit/SnapKit.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/Timepiece/Timepiece.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "PredicateEditor" -framework "SnapKit" -framework "StackViewController" -framework "Timepiece" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/NSDateComponents+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDateComponents+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Mattijs on 25/04/15. 6 | // Copyright (c) 2015 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension NSDateComponents { 12 | convenience init(_ duration: Duration) { 13 | self.init() 14 | switch duration.unit{ 15 | case NSCalendarUnit.Day: 16 | day = duration.value 17 | case NSCalendarUnit.Weekday: 18 | weekday = duration.value 19 | case NSCalendarUnit.WeekOfMonth: 20 | weekOfMonth = duration.value 21 | case NSCalendarUnit.WeekOfYear: 22 | weekOfYear = duration.value 23 | case NSCalendarUnit.Hour: 24 | hour = duration.value 25 | case NSCalendarUnit.Minute: 26 | minute = duration.value 27 | case NSCalendarUnit.Month: 28 | month = duration.value 29 | case NSCalendarUnit.Second: 30 | second = duration.value 31 | case NSCalendarUnit.Year: 32 | year = duration.value 33 | default: 34 | () // unsupported / ignore 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/ErrorToastView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorToastView.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 25/07/16. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | class ErrorToastView: UIView { 12 | let label: UILabel = { 13 | let label = UILabel() 14 | label.textAlignment = .Center 15 | label.numberOfLines = 0 16 | label.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical) 17 | label.textColor = UIColor.whiteColor() 18 | return label 19 | }() 20 | 21 | convenience init(message: String){ 22 | self.init(frame: CGRectZero) 23 | label.text = message 24 | } 25 | 26 | override init(frame: CGRect) { 27 | super.init(frame: frame) 28 | commonInit() 29 | } 30 | 31 | required init?(coder aDecoder: NSCoder) { 32 | super.init(coder: aDecoder) 33 | commonInit() 34 | } 35 | 36 | func commonInit() { 37 | setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical) 38 | addSubview(label) 39 | label.snp_makeConstraints { (make) in 40 | make.edges.equalTo(self).inset(10).priority(900) 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/PredicateComparable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PredicateComparable.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 12/07/16. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol PredicateComparable { 12 | func constantValue() -> AnyObject 13 | } 14 | 15 | extension String: PredicateComparable { 16 | public func constantValue() -> AnyObject { 17 | return self 18 | } 19 | } 20 | 21 | extension NSDate: PredicateComparable { 22 | public func constantValue() -> AnyObject { 23 | return self 24 | } 25 | } 26 | 27 | extension NSNumber: PredicateComparable { 28 | public func constantValue() -> AnyObject { 29 | return self 30 | } 31 | } 32 | 33 | extension Int: PredicateComparable { 34 | public func constantValue() -> AnyObject { 35 | return NSNumber(integer: self) 36 | } 37 | } 38 | 39 | extension Bool: PredicateComparable { 40 | public func constantValue() -> AnyObject { 41 | return NSNumber(bool: self) 42 | } 43 | } 44 | 45 | extension Float: PredicateComparable { 46 | public func constantValue() -> AnyObject { 47 | return NSNumber(float: self) 48 | } 49 | } 50 | 51 | extension Double: PredicateComparable { 52 | public func constantValue() -> AnyObject { 53 | return NSNumber(double: self) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/Int+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Int+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Naoto Kaneko on 2014/08/15. 6 | // Copyright (c) 2014年 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public extension Int { 12 | var year: Duration { 13 | return Duration(value: self, unit: .Year) 14 | } 15 | var years: Duration { 16 | return year 17 | } 18 | 19 | var month: Duration { 20 | return Duration(value: self, unit: .Month) 21 | } 22 | var months: Duration { 23 | return month 24 | } 25 | 26 | var week: Duration { 27 | return Duration(value: self, unit: .WeekOfYear) 28 | } 29 | var weeks: Duration { 30 | return week 31 | } 32 | 33 | var day: Duration { 34 | return Duration(value: self, unit: .Day) 35 | } 36 | var days: Duration { 37 | return day 38 | } 39 | 40 | var hour: Duration { 41 | return Duration(value: self, unit: .Hour) 42 | } 43 | var hours: Duration { 44 | return hour 45 | } 46 | 47 | var minute: Duration { 48 | return Duration(value: self, unit: .Minute) 49 | } 50 | var minutes: Duration { 51 | return minute 52 | } 53 | 54 | var second: Duration { 55 | return Duration(value: self, unit: .Second) 56 | } 57 | var seconds: Duration { 58 | return second 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/Duration.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Duration.swift 3 | // Timepiece 4 | // 5 | // Created by Naoto Kaneko on 2014/08/17. 6 | // Copyright (c) 2014年 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | prefix func - (duration: Duration) -> (Duration) { 12 | return Duration(value: -duration.value, unit: duration.unit) 13 | } 14 | 15 | public class Duration { 16 | public let value: Int 17 | public let unit: NSCalendarUnit 18 | private let calendar = NSCalendar.currentCalendar() 19 | 20 | /** 21 | Initialize a date before a duration. 22 | */ 23 | public var ago: NSDate { 24 | return ago(from: NSDate()) 25 | } 26 | 27 | public func ago(from date: NSDate) -> NSDate { 28 | return calendar.dateByAddingDuration(-self, toDate: date, options: .SearchBackwards)! 29 | } 30 | 31 | /** 32 | Initialize a date after a duration. 33 | */ 34 | public var later: NSDate { 35 | return later(from: NSDate()) 36 | } 37 | 38 | public func later(from date: NSDate) -> NSDate { 39 | return calendar.dateByAddingDuration(self, toDate: date, options: .SearchBackwards)! 40 | } 41 | 42 | /** 43 | This conversion is deprecated in 0.4.1 and will be obsoleted in 0.5.0. 44 | 45 | This operation is performed under incorrect assumption that 1 month is always equal to 30 days. 46 | */ 47 | public lazy var interval: NSTimeInterval = { [unowned self] in 48 | return self.unit.interval * NSTimeInterval(self.value) 49 | }() 50 | 51 | public init(value: Int, unit: NSCalendarUnit) { 52 | self.value = value 53 | self.unit = unit 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/SnapKit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | public typealias InterfaceLayoutDirection = UIUserInterfaceLayoutDirection 27 | public typealias LayoutSupport = UILayoutSupport 28 | #else 29 | import AppKit 30 | public typealias InterfaceLayoutDirection = NSUserInterfaceLayoutDirection 31 | public class LayoutSupport {} 32 | #endif 33 | 34 | /** 35 | Used to configure different parts of SnapKit 36 | */ 37 | public struct Config { 38 | 39 | /// The interface layout direction 40 | public static var interfaceLayoutDirection = InterfaceLayoutDirection.LeftToRight 41 | 42 | } -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/NSTimeInterval+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimeInterval+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Mattijs on 10/05/15. 6 | // Copyright (c) 2015 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | This extension is deprecated in 0.4.1 and will be obsoleted in 0.5.0. 13 | 14 | The conversion of Duration into NSTimeInterval is performed under incorrect assumption that 1 month is always equal to 30 days. 15 | Therefore, The comparison between Duration and NSTimeInterval is also incorrect. 16 | */ 17 | 18 | public func < (lhs: NSTimeInterval, rhs: Duration) -> Bool { 19 | return lhs < rhs.interval 20 | } 21 | 22 | public func < (lhs: Duration, rhs: NSTimeInterval) -> Bool { 23 | return lhs.interval < rhs 24 | } 25 | 26 | public func > (lhs: NSTimeInterval, rhs: Duration) -> Bool { 27 | return lhs > rhs.interval 28 | } 29 | 30 | public func > (lhs: Duration, rhs: NSTimeInterval) -> Bool { 31 | return lhs.interval > rhs 32 | } 33 | 34 | public func == (lhs: NSTimeInterval, rhs: Duration) -> Bool { 35 | return lhs == rhs.interval 36 | } 37 | 38 | public func == (lhs: Duration, rhs: NSTimeInterval) -> Bool { 39 | return lhs.interval == rhs 40 | } 41 | 42 | public func >= (lhs: NSTimeInterval, rhs: Duration) -> Bool { 43 | return lhs >= rhs.interval 44 | } 45 | 46 | public func >= (lhs: Duration, rhs: NSTimeInterval) -> Bool { 47 | return lhs.interval >= rhs 48 | } 49 | 50 | public func <= (lhs: NSTimeInterval, rhs: Duration) -> Bool { 51 | return lhs <= rhs.interval 52 | } 53 | 54 | public func <= (lhs: Duration, rhs: NSTimeInterval) -> Bool { 55 | return lhs.interval <= rhs 56 | } 57 | 58 | public func != (lhs: NSTimeInterval, rhs: Duration) -> Bool { 59 | return lhs != rhs.interval 60 | } 61 | 62 | public func != (lhs: Duration, rhs: NSTimeInterval) -> Bool { 63 | return lhs.interval != rhs 64 | } -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/NSCalendarUnit+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSCalendarUnit+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Mattijs on 13/05/15. 6 | // Copyright (c) 2015 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | This extension is deprecated in 0.4.1 and will be obsoleted in 0.5.0. 13 | 14 | The conversion of Duration into NSTimeInterval is performed under incorrect assumption that 1 month is always equal to 30 days. 15 | Therefore, The comparison between Duration and NSTimeInterval is also incorrect. 16 | */ 17 | public extension NSCalendarUnit { 18 | public var interval: NSTimeInterval { 19 | switch self { 20 | case NSCalendarUnit.Nanosecond: return 1e-9 // 1e-9 second 21 | case NSCalendarUnit.Second: return 1 // 1 second 22 | case NSCalendarUnit.Minute: return 60 // 1 minute 23 | case NSCalendarUnit.Hour: return 3600 // 1 hour 24 | case NSCalendarUnit.Weekday, 25 | NSCalendarUnit.WeekdayOrdinal, 26 | NSCalendarUnit.Day: return 86400 // 1 day 27 | case NSCalendarUnit.WeekOfYear, 28 | NSCalendarUnit.WeekOfMonth: return 604800 // 7 days 29 | case NSCalendarUnit.Month: return 2592000 // 30 days 30 | case NSCalendarUnit.YearForWeekOfYear, 31 | NSCalendarUnit.Quarter: return 146097/400/4*86400 // ~91.31 days 32 | case NSCalendarUnit.Year: return 146097/400*86400 // ~365.25 days 33 | // 400 years have 146097 days (taking into account leap year rules) 34 | 35 | default: 36 | print("warn: .interval for NSCalendarUnit(\(self.rawValue)) can't be determined. Returning 0.") 37 | return 0 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/ConstraintRelation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | /** 31 | Used to define `NSLayoutRelation` 32 | */ 33 | internal enum ConstraintRelation: Int { 34 | case Equal = 1, LessThanOrEqualTo, GreaterThanOrEqualTo 35 | 36 | internal var layoutRelation: NSLayoutRelation { 37 | get { 38 | switch(self) { 39 | case .LessThanOrEqualTo: 40 | return .LessThanOrEqual 41 | case .GreaterThanOrEqualTo: 42 | return .GreaterThanOrEqual 43 | default: 44 | return .Equal 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/EdgeInsets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | public typealias EdgeInsets = UIEdgeInsets 27 | public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets { 28 | return EdgeInsets(top: top, left: left, bottom: bottom, right: right) 29 | } 30 | public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 31 | #else 32 | import AppKit 33 | public typealias EdgeInsets = NSEdgeInsets 34 | public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets { 35 | return EdgeInsets(top: top, left: left, bottom: bottom, right: right) 36 | } 37 | public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 38 | #endif 39 | -------------------------------------------------------------------------------- /PredicateEditor.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint PredicateEditor.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'PredicateEditor' 11 | s.version = '0.9.1' 12 | s.summary = 'A visual editor for dynamically creating NSPredicates to query data in your app.' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = "PredicateEditor allows users of your apps to dynamically create filters (in the form of NSPredicates) using an easy-to-use GUI, that can then be used to filter data." 21 | 22 | s.homepage = 'https://github.com/arvindhsukumar/PredicateEditor' 23 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 24 | s.license = { :type => 'MIT', :file => 'LICENSE' } 25 | s.author = 'Arvindh Sukumar' 26 | s.source = { :git => 'https://github.com/arvindhsukumar/PredicateEditor.git', :tag => s.version.to_s } 27 | # s.social_media_url = 'https://twitter.com/' 28 | 29 | s.ios.deployment_target = '9.0' 30 | 31 | s.source_files = 'PredicateEditor/Classes/**/*' 32 | 33 | s.resource_bundles = { 34 | 'PredicateEditor' => ['PredicateEditor/Assets/*.png','PredicateEditor/Assets/*.xcassets'] 35 | } 36 | 37 | # s.public_header_files = 'Pod/Classes/**/*.h' 38 | # s.frameworks = 'UIKit', 'MapKit' 39 | s.dependency 'SnapKit', '~> 0.21' 40 | s.dependency 'SeedStackViewController', '~> 0.2' 41 | s.dependency 'Timepiece', '~> 0.4' 42 | end 43 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/SemiModalTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SemiModalTransition.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 18/07/16. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | protocol SemiModalViewable { 12 | var dimView: UIView! {get set} 13 | } 14 | 15 | class SemiModalTransition: NSObject, UIViewControllerAnimatedTransitioning { 16 | var presenting: Bool = false 17 | 18 | func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { 19 | return presenting ? 0.5 : 0.3 20 | } 21 | 22 | func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 23 | guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey), let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey), let containerView = transitionContext.containerView() else 24 | { 25 | return 26 | } 27 | 28 | if(presenting) 29 | { 30 | containerView.addSubview(toViewController.view) 31 | } 32 | 33 | let animatingVC = presenting ? toViewController: fromViewController 34 | let animatingView = animatingVC.view 35 | 36 | var appearedFrame = transitionContext.finalFrameForViewController(animatingVC) 37 | var dismissedFrame = appearedFrame; 38 | dismissedFrame.origin.y += dismissedFrame.size.height 39 | 40 | var initialFrame = presenting ? dismissedFrame : appearedFrame 41 | var finalFrame = presenting ? appearedFrame : dismissedFrame 42 | 43 | animatingView.frame = initialFrame 44 | 45 | UIView.animateWithDuration(transitionDuration(transitionContext), animations: { 46 | 47 | animatingView.frame = finalFrame 48 | 49 | }) { 50 | finished in 51 | 52 | if !self.presenting { 53 | fromViewController.view.removeFromSuperview() 54 | } 55 | transitionContext.completeTransition(true) 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Example/PredicateEditor/PersonTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PersonTableViewCell.swift 3 | // PredicateEditor 4 | // 5 | // Created by Arvindh Sukumar on 24/07/16. 6 | // Copyright © 2016 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let kPersonCellIdentifier = "PersonCell" 12 | 13 | class PersonTableViewCell: UITableViewCell { 14 | let nameLabel: UILabel = { 15 | let label = UILabel() 16 | label.font = UIFont.boldSystemFontOfSize(17) 17 | label.backgroundColor = UIColor.whiteColor() 18 | return label 19 | }() 20 | 21 | let detailsLabel: UILabel = { 22 | let label = UILabel() 23 | label.font = UIFont.systemFontOfSize(14) 24 | label.numberOfLines = 0 25 | label.textColor = UIColor(white: 0.4, alpha: 1) 26 | label.backgroundColor = UIColor.whiteColor() 27 | return label 28 | }() 29 | 30 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 31 | super.init(style: style, reuseIdentifier: reuseIdentifier) 32 | setupView() 33 | } 34 | 35 | required init?(coder aDecoder: NSCoder) { 36 | super.init(coder: aDecoder) 37 | setupView() 38 | } 39 | 40 | override func awakeFromNib() { 41 | super.awakeFromNib() 42 | // Initialization code 43 | } 44 | 45 | private func setupView(){ 46 | contentView.addSubview(nameLabel) 47 | nameLabel.snp_makeConstraints { (make) in 48 | make.left.equalTo(contentView).offset(16) 49 | make.top.equalTo(contentView).offset(10) 50 | make.right.equalTo(contentView).offset(-16) 51 | } 52 | 53 | contentView.addSubview(detailsLabel) 54 | detailsLabel.snp_makeConstraints { (make) in 55 | make.top.equalTo(nameLabel.snp_bottom).offset(2) 56 | make.bottom.equalTo(contentView).offset(-10) 57 | make.right.equalTo(nameLabel) 58 | make.left.equalTo(nameLabel) 59 | } 60 | } 61 | 62 | override func setSelected(selected: Bool, animated: Bool) { 63 | super.setSelected(selected, animated: animated) 64 | 65 | // Configure the view for the selected state 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/ViewController+SnapKit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | 27 | /** 28 | Used to expose public API on view controllers 29 | */ 30 | public extension UIViewController { 31 | 32 | /// top layout guide top 33 | public var snp_topLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Top) } 34 | 35 | /// top layout guide bottom 36 | public var snp_topLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Bottom) } 37 | 38 | /// bottom layout guide top 39 | public var snp_bottomLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Top) } 40 | 41 | /// bottom layout guide bottom 42 | public var snp_bottomLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Bottom) } 43 | 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /Example/PredicateEditor/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PredicateEditor 4 | // 5 | // Created by Arvindh Sukumar on 07/07/2016. 6 | // Copyright (c) 2016 Arvindh Sukumar. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/LayoutConstraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | /** 31 | Used to add extra information to the actual `NSLayoutConstraint`'s that will UIKit/AppKit will utilize 32 | */ 33 | public class LayoutConstraint: NSLayoutConstraint { 34 | 35 | internal var snp_constraint: Constraint? = nil 36 | 37 | } 38 | 39 | internal func ==(left: LayoutConstraint, right: LayoutConstraint) -> Bool { 40 | if left.firstItem !== right.firstItem { 41 | return false 42 | } 43 | if left.secondItem !== right.secondItem { 44 | return false 45 | } 46 | if left.firstAttribute != right.firstAttribute { 47 | return false 48 | } 49 | if left.secondAttribute != right.secondAttribute { 50 | return false 51 | } 52 | if left.relation != right.relation { 53 | return false 54 | } 55 | if left.priority != right.priority { 56 | return false 57 | } 58 | if left.multiplier != right.multiplier { 59 | return false 60 | } 61 | return true 62 | } 63 | 64 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/ConstraintItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | /** 31 | Used to assist in building a constraint 32 | */ 33 | public class ConstraintItem { 34 | 35 | internal init(object: AnyObject?, attributes: ConstraintAttributes) { 36 | self.object = object 37 | self.attributes = attributes 38 | } 39 | 40 | internal weak var object: AnyObject? 41 | internal var attributes: ConstraintAttributes 42 | 43 | internal var view: View? { 44 | return self.object as? View 45 | } 46 | 47 | @available(iOS 7.0, *) 48 | internal var layoutSupport: LayoutSupport? { 49 | return self.object as? LayoutSupport 50 | } 51 | } 52 | 53 | 54 | internal func ==(left: ConstraintItem, right: ConstraintItem) -> Bool { 55 | if left.object == nil { 56 | return false 57 | } 58 | if right.object == nil { 59 | return false 60 | } 61 | if left.object !== right.object { 62 | return false 63 | } 64 | if left.attributes != right.attributes { 65 | return false 66 | } 67 | return true 68 | } -------------------------------------------------------------------------------- /PredicateEditor/Classes/Section.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Section.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 07/07/16. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | public enum SectionPredicateType { 12 | case AND 13 | case OR 14 | } 15 | 16 | public class Section { 17 | public var title: String 18 | public var keyPathDescriptors: [KeyPathDescriptor] = [] 19 | public var rows: [Row] = [] 20 | public var compoundPredicateType: SectionPredicateType = .AND 21 | var keyPathTitles: [String] { 22 | return keyPathDescriptors.map({ (descriptor:KeyPathDescriptor) -> String in 23 | return descriptor.title 24 | }) 25 | } 26 | 27 | public init(title: String, keyPaths: [KeyPathDescriptor]){ 28 | self.title = title 29 | self.keyPathDescriptors = keyPaths 30 | } 31 | 32 | public func predicates() throws -> [NSPredicate] { 33 | let predicates = try rows.flatMap { (row:Row) -> NSPredicate? in 34 | do { 35 | return try row.toPredicate() 36 | } 37 | } 38 | return predicates 39 | } 40 | 41 | internal func ANDPredicate() throws -> NSCompoundPredicate { 42 | return try NSCompoundPredicate(andPredicateWithSubpredicates: predicates()) 43 | } 44 | 45 | internal func ORPredicate() throws -> NSCompoundPredicate { 46 | return try NSCompoundPredicate(orPredicateWithSubpredicates: predicates()) 47 | } 48 | 49 | public func compoundPredicate() throws -> NSCompoundPredicate { 50 | return try compoundPredicateType == .OR ? ORPredicate() : ANDPredicate() 51 | } 52 | } 53 | 54 | extension Section { 55 | public func append(row: Row) { 56 | // TODO: Check if row's descriptor is included in section? 57 | rows.append(row) 58 | row.section = self 59 | } 60 | 61 | public func insertRow(row: Row, atIndex: Int){ 62 | rows.insert(row, atIndex: atIndex) 63 | } 64 | 65 | public func deleteRow(row: Row){ 66 | for (i,r) in rows.enumerate() { 67 | if row === r { 68 | rows.removeAtIndex(i) 69 | } 70 | } 71 | } 72 | } 73 | 74 | extension Section { 75 | func descriptorWithTitle(title: String) -> KeyPathDescriptor? { 76 | return keyPathDescriptors.filter({ (descriptor:KeyPathDescriptor) -> Bool in 77 | return descriptor.title == title 78 | }).first 79 | } 80 | } -------------------------------------------------------------------------------- /Example/PredicateEditor/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/README.md: -------------------------------------------------------------------------------- 1 | # Timepiece [![Version](http://img.shields.io/cocoapods/v/Timepiece.svg?style=flat)](http://cocoadocs.org/docsets/Timepiece) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Build Status](https://travis-ci.org/naoty/Timepiece.svg?branch=travis-ci)](https://travis-ci.org/naoty/Timepiece) 2 | Intuitive NSDate extensions in Swift 3 | 4 | ## Usage 5 | 6 | ### Add durations to date 7 | 8 | ```swift 9 | let now = NSDate() 10 | let nextWeek = now + 1.week 11 | let dayAfterTomorrow = now + 2.days 12 | 13 | // shortcuts #1 14 | let today = NSDate.today() 15 | let tomorrow = NSDate.tomorrow() 16 | let yesterday = NSDate.yesterday() 17 | 18 | // shortcuts #2 19 | let dayBeforeYesterday = 2.days.ago 20 | let tokyoOlympicYear = 5.years.later 21 | ``` 22 | 23 | ### Initialize by specifying date components 24 | 25 | ```swift 26 | let birthday = NSDate.date(year: 1987, month: 6, day: 2) 27 | let firstCommitDate = NSDate.date(year: 2014, month: 8, day: 15, hour: 20, minute: 25, second: 43) 28 | ``` 29 | 30 | ### Initialize by changing date components 31 | 32 | ```swift 33 | let now = NSDate() 34 | let christmas = now.change(month: 12, day: 25) 35 | let thisSunday = now.change(weekday: 1) 36 | 37 | // shortcuts 38 | let newYearDay = now.beginningOfYear 39 | let timeLimit = now.endOfHour 40 | ``` 41 | 42 | ### Time zone 43 | 44 | ```swift 45 | let now = NSDate() 46 | let cst = NSTimeZone(name: "CST")! 47 | let dateInCST = now.beginningOfDay.change(timeZone: cst) 48 | dateInCST.timeZone //=> CST (CDT) offset -18000 (Daylight) 49 | ``` 50 | 51 | ### Format and parse 52 | 53 | ```swift 54 | 5.minutes.later.stringFromFormat("yyyy-MM-dd HH:mm:SS") 55 | //=> "2015-03-01 12:05:00" 56 | 57 | "1987-06-02".dateFromFormat("yyyy-MM-dd") 58 | //=> NSDate.date(year: 1987, month: 6, day: 2) 59 | ``` 60 | 61 | ### Compare dates 62 | 63 | ```swift 64 | firstCommitDate < 1.year.ago // false 65 | (1.year.ago...now).contains(firstCommitDate) // true 66 | firstCommitDate > now // false 67 | ``` 68 | 69 | ## Installation 70 | 71 | ### CocoaPods 72 | 73 | ```ruby 74 | # Podfile 75 | pod "Timepiece" 76 | ``` 77 | 78 | ### Carthage 79 | 80 | ```ruby 81 | # Cartfile 82 | github "naoty/Timepiece" 83 | ``` 84 | 85 | ## Contribution 86 | 87 | 1. Fork 88 | 2. Create your feature branch (git checkout -b my-new-feature) 89 | 3. Commit your changes (git commit -am 'Add some feature') 90 | 4. Push to the branch (git push origin my-new-feature) 91 | 5. Create new Pull Request 92 | 93 | ## License 94 | 95 | Timepiece is available under the MIT license. See the LICENSE file for more info. 96 | 97 | ## Author 98 | 99 | [naoty](https://github.com/naoty) 100 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/SeparatorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SeparatorView.swift 3 | // StackViewController 4 | // 5 | // Created by Indragie Karunaratne on 2016-04-12. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// A customizable separator view that can be displayed in horizontal and 12 | /// vertical orientations. 13 | public class SeparatorView: UIView { 14 | private var sizeConstraint: NSLayoutConstraint? 15 | 16 | /// The thickness of the separator. This is equivalent to the height for 17 | /// a horizontal separator and the width for a vertical separator. 18 | public var separatorThickness: CGFloat = 1.0 { 19 | didSet { 20 | sizeConstraint?.constant = separatorThickness 21 | setNeedsDisplay() 22 | } 23 | } 24 | 25 | /// The inset of the separator from the left (MinX) edge for a horizontal 26 | /// separator and from the bottom (MaxY) edge for a vertical separator. 27 | public var separatorInset: CGFloat = 15.0 { 28 | didSet { setNeedsDisplay() } 29 | } 30 | 31 | /// The color of the separator 32 | public var separatorColor = UIColor(white: 0.90, alpha: 1.0) { 33 | didSet { setNeedsDisplay() } 34 | } 35 | 36 | /// The axis (horizontal or vertical) of the separator 37 | public var axis = UILayoutConstraintAxis.Horizontal { 38 | didSet { updateSizeConstraint() } 39 | } 40 | 41 | /// Initializes the receiver for display on the specified axis. 42 | public init(axis: UILayoutConstraintAxis) { 43 | self.axis = axis 44 | super.init(frame: CGRectZero) 45 | commonInit() 46 | } 47 | 48 | required public init?(coder aDecoder: NSCoder) { 49 | super.init(coder: aDecoder) 50 | commonInit() 51 | } 52 | 53 | private func updateSizeConstraint() { 54 | sizeConstraint?.active = false 55 | let layoutAttribute: NSLayoutAttribute = { 56 | switch axis { 57 | case .Horizontal: return .Height 58 | case .Vertical: return .Width 59 | } 60 | }() 61 | sizeConstraint = NSLayoutConstraint( 62 | item: self, 63 | attribute: layoutAttribute, 64 | relatedBy: .Equal, 65 | toItem: nil, attribute: 66 | .NotAnAttribute, 67 | multiplier: 1.0, 68 | constant: separatorThickness 69 | ) 70 | sizeConstraint?.active = true 71 | } 72 | 73 | private func commonInit() { 74 | backgroundColor = .clearColor() 75 | updateSizeConstraint() 76 | } 77 | 78 | public override func drawRect(rect: CGRect) { 79 | guard separatorThickness > 0 else { return } 80 | let edge: CGRectEdge = { 81 | switch axis { 82 | case .Horizontal: return .MinXEdge 83 | case .Vertical: return .MaxYEdge 84 | } 85 | }() 86 | let (_, separatorRect) = bounds.divide(separatorInset, fromEdge: edge) 87 | separatorColor.setFill() 88 | UIRectFill(separatorRect) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Example/PredicateEditor/Playground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | 5 | var str = "Hello, playground" 6 | 7 | let kp = KeyPathDescriptor(keyPath: "test") { 8 | $0.displayString = "no" 9 | } 10 | 11 | public enum SectionPredicateType { 12 | case AND 13 | case OR 14 | } 15 | 16 | public class Section { 17 | public var title: String 18 | public var keyPathDescriptors: [KeyPathDescriptor] = [] 19 | public var rows: [Row] = [] 20 | public var compoundPredicateType: SectionPredicateType = .OR 21 | 22 | 23 | public init(title: String, keyPaths: [KeyPathDescriptor]){ 24 | self.title = title 25 | self.keyPathDescriptors = keyPaths 26 | } 27 | 28 | public func predicates() throws -> [NSPredicate] { 29 | let predicates = try rows.flatMap { (row:Row) -> NSPredicate? in 30 | do { 31 | return try row.toPredicate() 32 | } 33 | } 34 | return predicates 35 | } 36 | 37 | internal func ANDPredicate() throws -> NSCompoundPredicate { 38 | return try NSCompoundPredicate(orPredicateWithSubpredicates: predicates()) 39 | } 40 | 41 | internal func ORPredicate() throws -> NSCompoundPredicate { 42 | return try NSCompoundPredicate(orPredicateWithSubpredicates: predicates()) 43 | } 44 | 45 | public func compoundPredicate() throws -> NSCompoundPredicate { 46 | return try compoundPredicateType == .OR ? ORPredicate() : ANDPredicate() 47 | } 48 | } 49 | 50 | extension Section { 51 | public func append(row: Row) { 52 | rows.append(row) 53 | } 54 | 55 | public func insertRow(row: Row, atIndex: Int){ 56 | rows.insert(row, atIndex: atIndex) 57 | } 58 | 59 | public func deleteRow(row: Row){ 60 | for (i,r) in rows.enumerate() { 61 | if row === r { 62 | rows.removeAtIndex(i) 63 | } 64 | } 65 | } 66 | } 67 | 68 | let descriptor = KeyPathDescriptor(keyPath: "name", displayString: "Age", propertyType: KeyPathPropertyType.String) 69 | let comparisonType: KeyPathComparisonType = .Is 70 | let value: String = "John" 71 | let row = Row(descriptor: descriptor, comparisonType: comparisonType, value: value) 72 | 73 | let descriptor2 = KeyPathDescriptor(keyPath: "dob", displayString: "Name", propertyType: KeyPathPropertyType.DateTime) 74 | let comparisonType2: KeyPathComparisonType = .IsAfter 75 | let value2 = NSDate(timeIntervalSince1970: 321312311) 76 | let row2 = Row() 77 | row2.descriptor = descriptor2 78 | row2.comparisonType = comparisonType2 79 | row2.value = ValueHolder(baseValue: value2) 80 | 81 | 82 | let section = Section(title: "Test", keyPaths: []) 83 | section.append(row!) 84 | //section.append(row2) 85 | 86 | do { 87 | let ps = try section.predicates() 88 | dump(ps) 89 | } 90 | catch { 91 | print(error) 92 | } 93 | 94 | class Person: NSObject { 95 | var name: String 96 | var funny: Bool = true 97 | var age: Int = 30 98 | var score: Float 99 | var dob: NSDate 100 | init(name: String, funny: Bool = true, age: Int = 30, score: Float = 100, dob: NSDate = NSDate()){ 101 | self.name = name 102 | self.funny = funny 103 | self.age = age 104 | self.score = score 105 | self.dob = dob 106 | } 107 | } 108 | 109 | let people = [Person(name: "Johnathan", funny: false, score: 25.2), Person(name: "john", age: 41), Person(name: "ben", age: 24, dob: NSDate(timeIntervalSince1970: 321312312))] 110 | let array = (people as NSArray) 111 | dump(try? (people as NSArray).filteredArrayUsingPredicate(section.ORPredicate())) 112 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/DatePickerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DatePickerViewController.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 18/07/16. 6 | // 7 | // 8 | 9 | import UIKit 10 | 11 | protocol DatePickerDelegate: class { 12 | func datePickerDidSelectDate(row: Row, date: NSDate, datePickerMode: UIDatePickerMode) 13 | } 14 | 15 | class DatePickerViewController: UIViewController { 16 | weak var delegate: DatePickerDelegate? 17 | var row: Row! 18 | var date: NSDate? 19 | var datePickerMode: UIDatePickerMode = .Date 20 | let datePicker: UIDatePicker = { 21 | let dp = UIDatePicker(frame: CGRectZero) 22 | dp.timeZone = NSTimeZone.defaultTimeZone() 23 | dp.backgroundColor = UIColor.whiteColor() 24 | dp.setContentCompressionResistancePriority(1000, forAxis: .Vertical) 25 | return dp 26 | }() 27 | 28 | let toolBar: UIToolbar = { 29 | let toolbar = UIToolbar(frame: CGRectZero) 30 | toolbar.translucent = false 31 | toolbar.backgroundColor = UIColor.whiteColor() 32 | return toolbar 33 | }() 34 | 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | let tapGR = UITapGestureRecognizer(target: self, action: #selector(DatePickerViewController.close(_:))) 38 | tapGR.delegate = self 39 | view.addGestureRecognizer(tapGR) 40 | setupDatePicker() 41 | setupToolbar() 42 | } 43 | 44 | override func didReceiveMemoryWarning() { 45 | super.didReceiveMemoryWarning() 46 | // Dispose of any resources that can be recreated. 47 | } 48 | 49 | func setupDatePicker() { 50 | datePicker.datePickerMode = datePickerMode 51 | if let date = date { 52 | datePicker.setDate(date, animated: false) 53 | } 54 | view.addSubview(datePicker) 55 | datePicker.snp_makeConstraints { (make) in 56 | make.left.equalTo(view) 57 | make.right.equalTo(view) 58 | make.bottom.equalTo(view) 59 | } 60 | } 61 | 62 | func setupToolbar() { 63 | let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: #selector(DatePickerViewController.doneButtonTapped(_:))) 64 | 65 | let cancelButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: #selector(DatePickerViewController.cancelButtonTapped(_:))) 66 | 67 | let flexiSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: self, action: nil) 68 | 69 | toolBar.setItems([cancelButton, flexiSpace, doneButton], animated: false) 70 | view.addSubview(toolBar) 71 | toolBar.snp_makeConstraints { (make) in 72 | make.height.equalTo(44) 73 | make.left.equalTo(view) 74 | make.right.equalTo(view) 75 | make.bottom.equalTo(datePicker.snp_top) 76 | } 77 | } 78 | 79 | func close(sender: UITapGestureRecognizer) { 80 | if sender.state == .Recognized { 81 | dismissViewControllerAnimated(true, completion: nil) 82 | } 83 | } 84 | 85 | func doneButtonTapped(sender:UIBarButtonItem) { 86 | delegate?.datePickerDidSelectDate(row, date: 87 | datePicker.date, datePickerMode: datePickerMode) 88 | dismissViewControllerAnimated(true, completion: nil) 89 | } 90 | 91 | func cancelButtonTapped(sender:UIBarButtonItem) { 92 | dismissViewControllerAnimated(true, completion: nil) 93 | } 94 | } 95 | 96 | extension DatePickerViewController: UIGestureRecognizerDelegate { 97 | func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { 98 | return touch.view == view 99 | } 100 | } 101 | 102 | 103 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/PredicateEditor/PredicateEditor.framework" 88 | install_framework "$BUILT_PRODUCTS_DIR/SeedStackViewController/StackViewController.framework" 89 | install_framework "$BUILT_PRODUCTS_DIR/SnapKit/SnapKit.framework" 90 | install_framework "$BUILT_PRODUCTS_DIR/Timepiece/Timepiece.framework" 91 | fi 92 | if [[ "$CONFIGURATION" == "Release" ]]; then 93 | install_framework "$BUILT_PRODUCTS_DIR/PredicateEditor/PredicateEditor.framework" 94 | install_framework "$BUILT_PRODUCTS_DIR/SeedStackViewController/StackViewController.framework" 95 | install_framework "$BUILT_PRODUCTS_DIR/SnapKit/SnapKit.framework" 96 | install_framework "$BUILT_PRODUCTS_DIR/Timepiece/Timepiece.framework" 97 | fi 98 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## PredicateEditor 5 | 6 | Copyright (c) 2016 Arvindh Sukumar 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | 27 | ## SeedStackViewController 28 | 29 | **Copyright (c) 2016 Seed Platform, Inc.** 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in 39 | all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | THE SOFTWARE. 48 | 49 | 50 | ## SnapKit 51 | 52 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 53 | 54 | Permission is hereby granted, free of charge, to any person obtaining a copy 55 | of this software and associated documentation files (the "Software"), to deal 56 | in the Software without restriction, including without limitation the rights 57 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58 | copies of the Software, and to permit persons to whom the Software is 59 | furnished to do so, subject to the following conditions: 60 | 61 | The above copyright notice and this permission notice shall be included in 62 | all copies or substantial portions of the Software. 63 | 64 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 66 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 67 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 68 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 69 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 70 | THE SOFTWARE. 71 | 72 | 73 | ## Timepiece 74 | 75 | The MIT License (MIT) 76 | 77 | Copyright (c) 2014 Naoto Kaneko 78 | 79 | Permission is hereby granted, free of charge, to any person obtaining a copy 80 | of this software and associated documentation files (the "Software"), to deal 81 | in the Software without restriction, including without limitation the rights 82 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 83 | copies of the Software, and to permit persons to whom the Software is 84 | furnished to do so, subject to the following conditions: 85 | 86 | The above copyright notice and this permission notice shall be included in all 87 | copies or substantial portions of the Software. 88 | 89 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 90 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 91 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 92 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 93 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 94 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 95 | SOFTWARE. 96 | 97 | 98 | Generated by CocoaPods - https://cocoapods.org 99 | -------------------------------------------------------------------------------- /Example/PredicateEditor.xcodeproj/xcshareddata/xcschemes/PredicateEditor-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/KeyPathDescriptor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Arvindh Sukumar on 07/07/16. 3 | // 4 | 5 | import Foundation 6 | import Timepiece 7 | 8 | enum InputType { 9 | case Text 10 | case Picker 11 | } 12 | 13 | public enum KeyPathPropertyType { 14 | case String 15 | case Int 16 | case Float 17 | case Double 18 | case Boolean 19 | case Date 20 | case Time 21 | case DateTime 22 | case Array 23 | 24 | public func comparisonTypes() -> [KeyPathComparisonType] { 25 | switch self { 26 | case .String: 27 | return [.Is, .IsNot, .Contains, .DoesNotContain, .BeginsWith, .EndsWith] 28 | case .Int, .Float, .Double: 29 | return [.Is, .IsNot, .IsGreaterThan, .IsGreaterThanOrEqualTo, .IsLessThan, .IsLessThanOrEqualTo] 30 | case .Date: 31 | return [.IsOn, .IsNotOn, .IsAfter, .IsBefore, .IsToday] 32 | case .Time: 33 | return [.IsExactly, .IsNotExactly, .IsAfter, .IsBefore] 34 | case .DateTime: 35 | return [.IsExactly, .IsNotExactly, .IsAfter, .IsBefore] 36 | case .Array: 37 | return [.Contains] 38 | case .Boolean: 39 | return [.Is, .IsNot] 40 | default: 41 | return [] 42 | } 43 | } 44 | } 45 | 46 | public enum KeyPathComparisonType: String { 47 | case Is = "is" 48 | case IsNot = "is not" 49 | case Contains = "contains" 50 | case DoesNotContain = "does not contain" 51 | case BeginsWith = "begins with" 52 | case EndsWith = "ends with" 53 | 54 | // Numbers 55 | case IsGreaterThan = "is greater than" 56 | case IsGreaterThanOrEqualTo = "is greater than or equal to" 57 | case IsLessThan = "is less than" 58 | case IsLessThanOrEqualTo = "is less than or equal to" 59 | 60 | // Dates & Times 61 | case IsOn = "is on" 62 | case IsNotOn = "is not on" 63 | case IsAfter = "is after" 64 | case IsBefore = "is before" 65 | case IsToday = "is today" 66 | case IsBetween = "is between" 67 | case IsExactly = "is exactly" 68 | case IsNotExactly = "is not exactly" 69 | 70 | func predicateOperatorType() -> NSPredicateOperatorType? { 71 | switch self { 72 | case .Is: 73 | return .EqualToPredicateOperatorType 74 | case .IsNot: 75 | return .NotEqualToPredicateOperatorType 76 | case .Contains: 77 | return .ContainsPredicateOperatorType 78 | case .DoesNotContain: 79 | return .ContainsPredicateOperatorType 80 | case .BeginsWith: 81 | return .BeginsWithPredicateOperatorType 82 | case .EndsWith: 83 | return .EndsWithPredicateOperatorType 84 | case .IsGreaterThan: 85 | return .GreaterThanPredicateOperatorType 86 | case .IsGreaterThanOrEqualTo: 87 | return .GreaterThanOrEqualToPredicateOperatorType 88 | case .IsLessThan: 89 | return .LessThanPredicateOperatorType 90 | case .IsLessThanOrEqualTo: 91 | return .LessThanOrEqualToPredicateOperatorType 92 | default: 93 | return nil 94 | } 95 | } 96 | 97 | func shouldNegate() -> Bool { 98 | switch self { 99 | case .DoesNotContain, .IsNotOn, .IsNotExactly: 100 | return true 101 | default: 102 | return false 103 | } 104 | } 105 | } 106 | 107 | enum UnitType { 108 | // For use with "in the last x" date/time comparison type 109 | case Year 110 | case Month 111 | case Week 112 | case Day 113 | case Hour 114 | case Minute 115 | case Second 116 | } 117 | 118 | public struct KeyPathDescriptor { 119 | public var title: String! 120 | public var keyPath: String 121 | public var propertyType: KeyPathPropertyType = .String 122 | public var enumerationOptions: [String] = [] 123 | let commonInit = { 124 | (inout descriptor: KeyPathDescriptor) in 125 | 126 | if descriptor.propertyType == .Boolean { 127 | descriptor.enumerationOptions = ["true", "false"] 128 | } 129 | } 130 | 131 | public init(keyPath: String, title: String, propertyType: KeyPathPropertyType){ 132 | self.keyPath = keyPath 133 | self.title = title 134 | self.propertyType = propertyType 135 | commonInit(&self) 136 | } 137 | 138 | public init(keyPath: String, @noescape initialiser: (inout descriptor: KeyPathDescriptor)->()){ 139 | self.keyPath = keyPath 140 | initialiser(descriptor: &self) 141 | commonInit(&self) 142 | } 143 | } 144 | 145 | extension KeyPathDescriptor { 146 | func inputType() -> InputType { 147 | if enumerationOptions.count > 0 { 148 | return .Picker 149 | } 150 | switch propertyType { 151 | case .String, .Int, .Float, .Double: 152 | return .Text 153 | default: 154 | return .Picker 155 | } 156 | } 157 | 158 | func keyboardType() -> UIKeyboardType { 159 | switch propertyType { 160 | case .Int: 161 | return .NumberPad 162 | case .Float, .Double: 163 | return .DecimalPad 164 | default: 165 | return .Default 166 | } 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Tests/Pods-PredicateEditor_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/StackViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StackViewController.swift 3 | // StackViewController 4 | // 5 | // Created by Indragie Karunaratne on 2016-04-11. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Provides a view controller composition based API on top of the 12 | /// `StackViewContainer` API. Instead of adding content views directly to a view, 13 | /// view controllers that control each content view are added as child view 14 | /// controllers via the API exposed in this class. Adding and removing these 15 | /// child view controllers is managed automatically. 16 | public class StackViewController: UIViewController { 17 | /// This is exposed for configuring `backgroundView`, `stackView` 18 | /// `axis`, and `separatorViewFactory`. All other operations should 19 | /// be performed via this controller and not directly via the container view. 20 | public lazy var stackViewContainer = StackViewContainer() 21 | 22 | private var _items = [StackViewItem]() 23 | 24 | /// The items displayed by this controller 25 | public var items: [StackViewItem] { 26 | get { return _items } 27 | set(newItems) { 28 | for (index, _) in _items.enumerate() { 29 | removeItemAtIndex(index) 30 | } 31 | for item in newItems { 32 | addItem(item, canShowSeparator: true) 33 | } 34 | } 35 | } 36 | private var viewControllers = [UIViewController]() 37 | 38 | public override func loadView() { 39 | view = stackViewContainer 40 | } 41 | 42 | /** 43 | Adds an item to the list of items managed by the controller. The item can 44 | be either a `UIView` or a `UIViewController`, both of which conform to the 45 | `StackViewItem` protocol. 46 | 47 | - parameter item: The item to add 48 | - parameter canShowSeparator: See the documentation for 49 | `StackViewContainer.setCanShowSeparator(:forContentViewAtIndex:)` for more 50 | details on this parameter. 51 | */ 52 | public func addItem(item: StackViewItem, canShowSeparator: Bool = true) { 53 | insertItem(item, atIndex: _items.endIndex, canShowSeparator: canShowSeparator) 54 | } 55 | 56 | /** 57 | Inserts an item into the list of items managed by the controller. The item can 58 | be either a `UIView` or a `UIViewController`, both of which conform to the 59 | `StackViewItem` protocol. 60 | 61 | - parameter item: The item to insert 62 | - parameter index: The index to insert the item at 63 | - parameter canShowSeparator: See the documentation for 64 | `StackViewContainer.setCanShowSeparator(:forContentViewAtIndex:)` for more 65 | details on this parameter. 66 | */ 67 | public func insertItem(item: StackViewItem, atIndex index: Int, canShowSeparator: Bool = true) { 68 | precondition(index >= _items.startIndex) 69 | precondition(index <= _items.endIndex) 70 | 71 | _items.insert(item, atIndex: index) 72 | let viewController = item.toViewController() 73 | viewControllers.insert(viewController, atIndex: index) 74 | addChildViewController(viewController) 75 | stackViewContainer.insertContentView(viewController.view, atIndex: index, canShowSeparator: canShowSeparator) 76 | } 77 | 78 | /** 79 | Removes an item from the list of items managed by this controller. If `item` 80 | does not exist in `items`, this method does nothing. 81 | 82 | - parameter item: The item to remove. 83 | */ 84 | public func removeItem(item: StackViewItem) { 85 | guard let index = _items.indexOf({ $0 === item }) else { return } 86 | removeItemAtIndex(index) 87 | } 88 | 89 | /** 90 | Removes an item from the list of items managed by this controller. 91 | 92 | - parameter index: The index of the item to remove 93 | */ 94 | public func removeItemAtIndex(index: Int) { 95 | _items.removeAtIndex(index) 96 | let viewController = viewControllers[index] 97 | viewController.willMoveToParentViewController(nil) 98 | stackViewContainer.removeContentViewAtIndex(index) 99 | viewController.removeFromParentViewController() 100 | viewControllers.removeAtIndex(index) 101 | } 102 | 103 | /** 104 | Sets whether a separator can be shown for `item` 105 | 106 | - parameter canShowSeparator: See the documentation for 107 | `StackViewContainer.setCanShowSeparator(:forContentViewAtIndex:)` for more 108 | details on this parameter. 109 | - parameter item: The item for which to configure separator 110 | visibility 111 | */ 112 | public func setCanShowSeparator(canShowSeparator: Bool, forItem item: StackViewItem) { 113 | guard let index = _items.indexOf({ $0 === item }) else { return } 114 | setCanShowSeparator(canShowSeparator, forItemAtIndex: index) 115 | } 116 | 117 | /** 118 | Sets whether a separator can be shown for the item at index `index` 119 | 120 | - parameter canShowSeparator: See the documentation for 121 | `StackViewContainer.setCanShowSeparator(:forContentViewAtIndex:)` for more 122 | details on this parameter. 123 | - parameter index: The index of the item to configure separator 124 | visibility for. 125 | */ 126 | public func setCanShowSeparator(canShowSeparator: Bool, forItemAtIndex index: Int) { 127 | stackViewContainer.setCanShowSeparator(canShowSeparator, forContentViewAtIndex: index) 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/StackViewController/AutoScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutoScrollView.swift 3 | // Seed 4 | // 5 | // Created by Indragie Karunaratne on 2016-03-10. 6 | // Copyright © 2016 Seed Platform, Inc. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// A scroll view that automatically scrolls to a subview of its `contentView` 12 | /// when the keyboard is shown. This replicates the behaviour implemented by 13 | /// `UITableView`. 14 | public class AutoScrollView: UIScrollView { 15 | private struct Constants { 16 | static let DefaultAnimationDuration: NSTimeInterval = 0.25 17 | static let DefaultAnimationCurve = UIViewAnimationCurve.EaseInOut 18 | static let ScrollAnimationID = "AutoscrollAnimation" 19 | } 20 | 21 | /// The content view to display inside the container view. Views can also 22 | /// be added directly to this view without using the `contentView` property, 23 | /// but it simply makes it more convenient for the common case where your 24 | /// content fills the bounds of the scroll view. 25 | public var contentView: UIView? { 26 | willSet { 27 | contentView?.removeFromSuperview() 28 | } 29 | didSet { 30 | if let contentView = contentView { 31 | addSubview(contentView) 32 | updateContentViewConstraints() 33 | } 34 | } 35 | } 36 | private var contentViewConstraints: [NSLayoutConstraint]? 37 | 38 | override public var contentInset: UIEdgeInsets { 39 | didSet { 40 | updateContentViewConstraints() 41 | } 42 | } 43 | 44 | private func updateContentViewConstraints() { 45 | if let constraints = contentViewConstraints { 46 | NSLayoutConstraint.deactivateConstraints(constraints) 47 | } 48 | if let contentView = contentView { 49 | contentViewConstraints = contentView.activateSuperviewHuggingConstraints(insets: contentInset) 50 | } else { 51 | contentViewConstraints = nil 52 | } 53 | } 54 | 55 | private func commonInit() { 56 | let nc = NSNotificationCenter.defaultCenter() 57 | nc.addObserver(self, selector: #selector(AutoScrollView.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil) 58 | nc.addObserver(self, selector: #selector(AutoScrollView.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) 59 | } 60 | 61 | public override init(frame: CGRect) { 62 | super.init(frame: frame) 63 | commonInit() 64 | } 65 | 66 | public required init?(coder aDecoder: NSCoder) { 67 | super.init(coder: aDecoder) 68 | commonInit() 69 | } 70 | 71 | deinit { 72 | NSNotificationCenter.defaultCenter().removeObserver(self) 73 | } 74 | 75 | // MARK: Notifications 76 | 77 | // Implementation based on code from Apple documentation 78 | // https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html 79 | @objc private func keyboardWillShow(notification: NSNotification) { 80 | let keyboardFrameValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue 81 | guard var keyboardFrame = keyboardFrameValue?.CGRectValue() else { return } 82 | keyboardFrame = convertRect(keyboardFrame, fromView: nil) 83 | 84 | let bottomInset: CGFloat 85 | let keyboardIntersectionRect = bounds.intersect(keyboardFrame) 86 | if !keyboardIntersectionRect.isNull { 87 | bottomInset = keyboardIntersectionRect.height 88 | let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: bottomInset, right: 0) 89 | super.contentInset = contentInset 90 | scrollIndicatorInsets = contentInset 91 | } else { 92 | bottomInset = 0.0 93 | } 94 | 95 | guard let firstResponder = firstResponder else { return } 96 | let firstResponderFrame = firstResponder.convertRect(firstResponder.bounds, toView: self) 97 | 98 | var contentBounds = CGRect(origin: contentOffset, size: bounds.size) 99 | contentBounds.size.height -= bottomInset 100 | if !contentBounds.contains(firstResponderFrame.origin) { 101 | let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSTimeInterval ?? Constants.DefaultAnimationDuration 102 | let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? UIViewAnimationCurve ?? Constants.DefaultAnimationCurve 103 | 104 | // Dropping down to the old style UIView animation API because the new API 105 | // does not support setting the curve directly. The other option is to take 106 | // `curve` and shift it left by 16 bits to turn it into a `UIViewAnimationOptions`, 107 | // but that seems uglier than just doing this. 108 | UIView.beginAnimations(Constants.ScrollAnimationID, context: nil) 109 | UIView.setAnimationCurve(curve) 110 | UIView.setAnimationDuration(duration) 111 | scrollRectToVisible(firstResponderFrame, animated: false) 112 | UIView.commitAnimations() 113 | } 114 | } 115 | 116 | @objc private func keyboardWillHide(notification: NSNotification) { 117 | super.contentInset = UIEdgeInsetsZero 118 | scrollIndicatorInsets = UIEdgeInsetsZero 119 | } 120 | } 121 | 122 | private extension UIView { 123 | var firstResponder: UIView? { 124 | if isFirstResponder() { 125 | return self 126 | } 127 | for subview in subviews { 128 | if let responder = subview.firstResponder { 129 | return responder 130 | } 131 | } 132 | return nil 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PredicateEditor 2 | 3 | PredicateEditor is a visual editor for creating and using NSPredicates for querying data in your app. 4 | 5 | ![Screenshot](http://i.imgur.com/m7PUa3el.png) 6 | 7 | PredicateEditor was inspired by the implementation in [Workflow](http://workflow.is) 8 | 9 | ## Features 10 | - Create filters for the following property types: `String`s, `NSDate`s, `NSNumber`s, `Int`s, `Float`s, and `Bool`s. 11 | - Easily define the properties & keyPaths you'd like to be able to filter on. 12 | - Filters can be added & deleted at will in the UI - The user can define as many filters as required. 13 | - Input types are automatically updated to reflect the property type - Strings, Dates, Numbers etc 14 | - Supports multiple sections of filters, each with its own compound predicate - AND or OR. Sections can again be clubbed together with other compound predicates. 15 | 16 | ## Installation 17 | 18 | PredicateEditor is available through [CocoaPods](http://cocoapods.org). To install 19 | it, simply add the following line to your Podfile: 20 | 21 | ```ruby 22 | pod "PredicateEditor" 23 | ``` 24 | 25 | ## Requirements 26 | - Requires Xcode 7.3 with Swift 2.2 27 | - Deployment target of iOS 9+ (due to liberal use of UIStackViews) 28 | 29 | **Please note that it's not possible to use this library in Obj-C code yet** 30 | 31 | ## Usage 32 | 33 | #### Creating the editor 34 | The first step in using the PredicateEditor is to create sections with the keyPaths you'd like to be made available for filtering. 35 | 36 | Sections are created using one or more `KeyPathDescriptor`s. Each of these describe the property that is to be filtered on, and the keyPath to use while filtering. 37 | 38 | In most cases, each section would correspond to a particular model in your app. 39 | 40 | ```swift 41 | var keyPaths: [KeyPathDescriptor] = [] 42 | 43 | //Assuming you have a Person model with properties `name`, `age`, `dateOfBirth` & a Bool `isDeveloper`, create a descriptor for each of them. 44 | let kp1 = KeyPathDescriptor(keyPath:"name", title: "Name", propertyType: .String) 45 | let kp2 = KeyPathDescriptor(keyPath:"dateOfBirth", title: "Date Of Birth", propertyType: .Date) 46 | let kp3 = KeyPathDescriptor(keyPath:"age", title: "Age", propertyType: .Int) 47 | let kp4 = KeyPathDescriptor(keyPath:"isDeveloper", title: "Is a Developer", propertyType: .Boolean) 48 | keyPaths = [kp1, kp2, kp3, kp4] 49 | 50 | let section = Section(title: "Filter People", keyPaths: keyPaths) 51 | ``` 52 | 53 | Now you can create a PredicateEditor View Controller instance, and present it: 54 | 55 | ```swift 56 | let predicateEditorVC = PredicateEditorViewController(sections: [section]) 57 | predicateEditorVC.delegate = self // Conform to PredicateEditorDelegate to receive callbacks. 58 | 59 | // Wrap the editor in a nav controller in order to be able to dismiss it. 60 | let nc = UINavigationController(rootViewController: predicateEditorVC) 61 | nc.modalTransitionStyle = .CoverVertical 62 | presentViewController(nc, animated: true, completion: nil) 63 | ``` 64 | 65 | #### Enumeration Options 66 | 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: 67 | 68 | ```swift 69 | let kp = KeyPathDescriptor(keyPath:"gender", title: "Gender", propertyType: .String) 70 | kp.enumerationOptions = ["Male", "Female"] 71 | ``` 72 | 73 | #### Editor Configuration 74 | Additionally create and pass a `PredicatedEditorConfig` object to the predicate editor during init. 75 | 76 | ```swift 77 | var config = PredicatorEditorConfig() 78 | config.backgroundColor = UIColor(white: 0.9, alpha: 1) 79 | config.sectionBackgroundColor = UIColor(white: 0.95, alpha: 1) 80 | ... 81 | 82 | let predicateEditor = PredicateEditorViewController(sections: [section], config: config) 83 | ``` 84 | 85 | #### Pre-defined Sections 86 | 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 `Row`s to the section. 87 | 88 | ```swift 89 | // For each filter you'd like to pre-define, create a Row with the descriptor, comparisonType and value. 90 | 91 | let descriptor = KeyPathDescriptor(keyPath: "name", title: "Name", propertyType: KeyPathPropertyType.String) 92 | let comparisonType: KeyPathComparisonType = .Contains 93 | let value = "John" 94 | if let row = Row(descriptor: descriptor, comparisonType: comparisonType, value: value){ 95 | section.append(row) 96 | } 97 | 98 | let descriptor2 = KeyPathDescriptor(keyPath: "dob", title: "Date of Birth", propertyType: KeyPathPropertyType.Date) 99 | let comparisonType2: KeyPathComparisonType = .IsAfter 100 | let value2 = NSDate(timeIntervalSince1970: 321312311) 101 | if let row2 = Row(descriptor: descriptor2, comparisonType: comparisonType2, value: value2){ 102 | section.append(row2) 103 | } 104 | ``` 105 | 106 | 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. 107 | 108 | #### Obtaining Predicates 109 | 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 `NSPredicate`s - one for each section. 110 | 111 | 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. 112 | 113 | ```swift 114 | let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates) 115 | let filteredPeople = (people as NSArray).filteredArrayUsingPredicate(compoundPredicate) as! [Person] 116 | ``` 117 | 118 | ## Example 119 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 120 | 121 | ## Todo: 122 | - Add an In-Between comparison type. 123 | - Add more configuration options. 124 | - Add support for filtering array property types. 125 | 126 | ## Author 127 | 128 | Arvindh Sukumar ([Github](https://www.github.com/arvindhsukumar)) 129 | 130 | ## License 131 | 132 | PredicateEditor is available under the MIT license. See the LICENSE file for more info. 133 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-PredicateEditor_Example/Pods-PredicateEditor_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2016 Arvindh Sukumar <arvindh.sukumar@gmail.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | Title 38 | PredicateEditor 39 | Type 40 | PSGroupSpecifier 41 | 42 | 43 | FooterText 44 | **Copyright (c) 2016 Seed Platform, Inc.** 45 | 46 | Permission is hereby granted, free of charge, to any person obtaining a copy 47 | of this software and associated documentation files (the "Software"), to deal 48 | in the Software without restriction, including without limitation the rights 49 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 50 | copies of the Software, and to permit persons to whom the Software is 51 | furnished to do so, subject to the following conditions: 52 | 53 | The above copyright notice and this permission notice shall be included in 54 | all copies or substantial portions of the Software. 55 | 56 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 57 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 58 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 59 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 60 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 61 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 62 | THE SOFTWARE. 63 | 64 | Title 65 | SeedStackViewController 66 | Type 67 | PSGroupSpecifier 68 | 69 | 70 | FooterText 71 | Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit 72 | 73 | Permission is hereby granted, free of charge, to any person obtaining a copy 74 | of this software and associated documentation files (the "Software"), to deal 75 | in the Software without restriction, including without limitation the rights 76 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 77 | copies of the Software, and to permit persons to whom the Software is 78 | furnished to do so, subject to the following conditions: 79 | 80 | The above copyright notice and this permission notice shall be included in 81 | all copies or substantial portions of the Software. 82 | 83 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 84 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 85 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 86 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 87 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 88 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 89 | THE SOFTWARE. 90 | 91 | Title 92 | SnapKit 93 | Type 94 | PSGroupSpecifier 95 | 96 | 97 | FooterText 98 | The MIT License (MIT) 99 | 100 | Copyright (c) 2014 Naoto Kaneko 101 | 102 | Permission is hereby granted, free of charge, to any person obtaining a copy 103 | of this software and associated documentation files (the "Software"), to deal 104 | in the Software without restriction, including without limitation the rights 105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 106 | copies of the Software, and to permit persons to whom the Software is 107 | furnished to do so, subject to the following conditions: 108 | 109 | The above copyright notice and this permission notice shall be included in all 110 | copies or substantial portions of the Software. 111 | 112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 118 | SOFTWARE. 119 | 120 | 121 | Title 122 | Timepiece 123 | Type 124 | PSGroupSpecifier 125 | 126 | 127 | FooterText 128 | Generated by CocoaPods - https://cocoapods.org 129 | Title 130 | 131 | Type 132 | PSGroupSpecifier 133 | 134 | 135 | StringsTable 136 | Acknowledgements 137 | Title 138 | Acknowledgements 139 | 140 | 141 | -------------------------------------------------------------------------------- /Example/Pods/Timepiece/Sources/NSDate+Timepiece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Timepiece.swift 3 | // Timepiece 4 | // 5 | // Created by Naoto Kaneko on 2014/08/16. 6 | // Copyright (c) 2014年 Naoto Kaneko. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import ObjectiveC 11 | 12 | // MARK: - Calculation 13 | 14 | public func + (lhs: NSDate, rhs: Duration) -> NSDate { 15 | return NSCalendar.currentCalendar().dateByAddingDuration(rhs, toDate: lhs, options: .SearchBackwards)! 16 | } 17 | 18 | public func - (lhs: NSDate, rhs: Duration) -> NSDate { 19 | return NSCalendar.currentCalendar().dateByAddingDuration(-rhs, toDate: lhs, options: .SearchBackwards)! 20 | } 21 | 22 | public func - (lhs: NSDate, rhs: NSDate) -> NSTimeInterval { 23 | return lhs.timeIntervalSinceDate(rhs) 24 | } 25 | 26 | // MARK: - Equatable 27 | 28 | //extension NSDate: Equatable {} 29 | 30 | public func == (lhs: NSDate, rhs: NSDate) -> Bool { 31 | return lhs.isEqualToDate(rhs) 32 | } 33 | 34 | // MARK: - Comparable 35 | 36 | extension NSDate: Comparable {} 37 | 38 | public func < (lhs: NSDate, rhs: NSDate) -> Bool { 39 | return lhs.compare(rhs) == .OrderedAscending 40 | } 41 | 42 | // MARK: - 43 | 44 | public extension NSDate { 45 | private struct AssociatedKeys { 46 | static var TimeZone = "timepiece_TimeZone" 47 | } 48 | 49 | // MARK: - Get components 50 | 51 | var year: Int { 52 | return components.year 53 | } 54 | 55 | var month: Int { 56 | return components.month 57 | } 58 | 59 | var weekday: Int { 60 | return components.weekday 61 | } 62 | 63 | var day: Int { 64 | return components.day 65 | } 66 | 67 | var hour: Int { 68 | return components.hour 69 | } 70 | 71 | var minute: Int { 72 | return components.minute 73 | } 74 | 75 | var second: Int { 76 | return components.second 77 | } 78 | 79 | var timeZone: NSTimeZone { 80 | return objc_getAssociatedObject(self, &AssociatedKeys.TimeZone) as? NSTimeZone ?? calendar.timeZone 81 | } 82 | 83 | private var components: NSDateComponents { 84 | return calendar.components([.Year, .Month, .Weekday, .Day, .Hour, .Minute, .Second], fromDate: self) 85 | } 86 | 87 | private var calendar: NSCalendar { 88 | return NSCalendar.currentCalendar() 89 | } 90 | 91 | // MARK: - Initialize 92 | 93 | class func date(year year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> NSDate { 94 | let now = NSDate() 95 | return now.change(year: year, month: month, day: day, hour: hour, minute: minute, second: second) 96 | } 97 | 98 | class func date(year year: Int, month: Int, day: Int) -> NSDate { 99 | return NSDate.date(year: year, month: month, day: day, hour: 0, minute: 0, second: 0) 100 | } 101 | 102 | class func today() -> NSDate { 103 | let now = NSDate() 104 | return NSDate.date(year: now.year, month: now.month, day: now.day) 105 | } 106 | 107 | class func yesterday() -> NSDate { 108 | return today() - 1.day 109 | } 110 | 111 | class func tomorrow() -> NSDate { 112 | return today() + 1.day 113 | } 114 | 115 | // MARK: - Initialize by setting components 116 | 117 | /** 118 | Initialize a date by changing date components of the receiver. 119 | */ 120 | func change(year year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil, second: Int? = nil) -> NSDate! { 121 | let components = self.components 122 | components.year = year ?? self.year 123 | components.month = month ?? self.month 124 | components.day = day ?? self.day 125 | components.hour = hour ?? self.hour 126 | components.minute = minute ?? self.minute 127 | components.second = second ?? self.second 128 | return calendar.dateFromComponents(components) 129 | } 130 | 131 | /** 132 | Initialize a date by changing the weekday of the receiver. 133 | */ 134 | func change(weekday weekday: Int) -> NSDate! { 135 | return self - (self.weekday - weekday).days 136 | } 137 | 138 | /** 139 | Initialize a date by changing the time zone of receiver. 140 | */ 141 | func change(timeZone timeZone: NSTimeZone) -> NSDate! { 142 | let originalTimeZone = calendar.timeZone 143 | calendar.timeZone = timeZone 144 | 145 | let newDate = calendar.dateFromComponents(components)! 146 | newDate.calendar.timeZone = timeZone 147 | objc_setAssociatedObject(newDate, &AssociatedKeys.TimeZone, timeZone, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 148 | 149 | calendar.timeZone = originalTimeZone 150 | 151 | return newDate 152 | } 153 | 154 | // MARK: - Initialize a date at beginning/end of each units 155 | 156 | var beginningOfYear: NSDate { 157 | return change(month: 1, day: 1, hour: 0, minute: 0, second: 0) 158 | } 159 | var endOfYear: NSDate { 160 | return change(month: 12, day: 31, hour: 23, minute: 59, second: 59) 161 | } 162 | 163 | var beginningOfMonth: NSDate { 164 | return change(day: 1, hour: 0, minute: 0, second: 0) 165 | } 166 | var endOfMonth: NSDate { 167 | let lastDay = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: self).length 168 | return change(day: lastDay, hour: 23, minute: 59, second: 59) 169 | } 170 | 171 | var beginningOfWeek: NSDate { 172 | let daysDiff = (7 + (weekday - calendar.firstWeekday)) % 7 173 | return beginningOfDay - daysDiff.days 174 | } 175 | var endOfWeek: NSDate { 176 | let daysDiff = (7 + ((calendar.firstWeekday - 1) - weekday)) % 7 177 | return endOfDay + daysDiff.days 178 | } 179 | 180 | var beginningOfDay: NSDate { 181 | return change(hour: 0, minute: 0, second: 0) 182 | } 183 | var endOfDay: NSDate { 184 | return change(hour: 23, minute: 59, second: 59) 185 | } 186 | 187 | var beginningOfHour: NSDate { 188 | return change(minute: 0, second: 0) 189 | } 190 | var endOfHour: NSDate { 191 | return change(minute: 59, second: 59) 192 | } 193 | 194 | var beginningOfMinute: NSDate { 195 | return change(second: 0) 196 | } 197 | var endOfMinute: NSDate { 198 | return change(second: 59) 199 | } 200 | 201 | // MARK: - Format dates 202 | 203 | func stringFromFormat(format: String) -> String { 204 | let formatter = NSDateFormatter() 205 | formatter.dateFormat = format 206 | return formatter.stringFromDate(self) 207 | } 208 | } -------------------------------------------------------------------------------- /PredicateEditor/Classes/PredicateEditorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PredicateEditorViewController.swift 3 | // Pods 4 | // 5 | // Created by Arvindh Sukumar on 07/07/16. 6 | // 7 | // 8 | 9 | import UIKit 10 | import StackViewController 11 | import SnapKit 12 | 13 | public struct PredicatorEditorConfig { 14 | public var keyPathDisplayColor: UIColor! 15 | public var comparisonButtonColor: UIColor! 16 | public var inputColor: UIColor! 17 | public var backgroundColor: UIColor! 18 | public var sectionBackgroundColor: UIColor! 19 | public var errorColor: UIColor! 20 | 21 | public init() { 22 | self.keyPathDisplayColor = UIColor(red:0.64, green:0.41, blue:0.65, alpha:1.00) 23 | self.comparisonButtonColor = UIColor(red:0.27, green:0.47, blue:0.74, alpha:1.00) 24 | self.inputColor = UIColor(red:0.00, green:0.53, blue:0.19, alpha:1.00) 25 | self.backgroundColor = UIColor(red:0.87, green:0.89, blue:0.93, alpha:1.00) 26 | self.sectionBackgroundColor = UIColor(red:0.94, green:0.95, blue:0.97, alpha:1.00) 27 | self.errorColor = UIColor(red:0.44, green:0.15, blue:0.20, alpha:1.00) 28 | } 29 | } 30 | 31 | @objc public protocol PredicateEditorDelegate { 32 | func predicateEditorDidFinishWithPredicates(predicates: [NSPredicate]) 33 | } 34 | 35 | public class PredicateEditorViewController: UIViewController { 36 | public weak var delegate: PredicateEditorDelegate? 37 | var config: PredicatorEditorConfig! 38 | var sections: [Section] = [] 39 | var sectionViews: [SectionView] = [] 40 | private let stackViewController: StackViewController 41 | 42 | public convenience init(sections:[Section], config: PredicatorEditorConfig = PredicatorEditorConfig() ) { 43 | self.init() 44 | self.sections = sections 45 | self.config = config 46 | } 47 | 48 | init() { 49 | stackViewController = StackViewController() 50 | stackViewController.stackViewContainer.separatorViewFactory = StackViewContainer.createSeparatorViewFactory() 51 | super.init(nibName: nil, bundle: nil) 52 | } 53 | 54 | required public init?(coder aDecoder: NSCoder) { 55 | fatalError("init(coder:) has not been implemented") 56 | } 57 | 58 | override public func viewDidLoad() { 59 | super.viewDidLoad() 60 | 61 | navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Cancel, target: self, action: #selector(PredicateEditorViewController.dismiss)) 62 | navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: #selector(PredicateEditorViewController.createPredicateAndDismiss)) 63 | 64 | edgesForExtendedLayout = .None 65 | setupStackView() 66 | } 67 | 68 | public override func viewWillAppear(animated: Bool) { 69 | super.viewWillAppear(animated) 70 | navigationController?.navigationBar.translucent = false 71 | } 72 | 73 | private func setupStackView(){ 74 | stackViewController.view.backgroundColor = config.backgroundColor 75 | addChildViewController(stackViewController) 76 | view.addSubview(stackViewController.view) 77 | stackViewController.view.snp_makeConstraints { 78 | make in 79 | make.edges.equalTo(view) 80 | } 81 | stackViewController.didMoveToParentViewController(self) 82 | stackViewController.stackViewContainer.scrollView.alwaysBounceVertical = true 83 | 84 | for section in sections { 85 | let sectionViewController = SectionViewController(section: section, config: config) 86 | stackViewController.addItem(sectionViewController) 87 | } 88 | } 89 | 90 | func dismiss() { 91 | dismissViewControllerAnimated(true, completion: nil) 92 | } 93 | 94 | func createPredicateAndDismiss() { 95 | do { 96 | try delegate?.predicateEditorDidFinishWithPredicates(predicates()) 97 | dismiss() 98 | } 99 | catch RowPredicateError.InsufficientData(keyPath: let keyPath) { 100 | var message: String = "Please update all filters" 101 | if let kp = keyPath { 102 | message = "Please update value for \"\(kp.title)\"" 103 | } 104 | showErrorToast(message) 105 | } 106 | catch { 107 | print(error) 108 | } 109 | } 110 | 111 | private func showErrorToast(message: String){ 112 | navigationItem.rightBarButtonItem?.enabled = false 113 | let toast = ErrorToastView(message: message) 114 | toast.backgroundColor = config.errorColor 115 | 116 | let tap = UITapGestureRecognizer(target: self, action: #selector(PredicateEditorViewController.dismissToastOnTap(_:))) 117 | 118 | var toastTopConstraint: Constraint! 119 | view.addSubview(toast) 120 | toast.snp_makeConstraints { (make) in 121 | make.left.equalTo(view) 122 | make.right.equalTo(view) 123 | toastTopConstraint = make.top.equalTo(view.snp_bottom).constraint 124 | } 125 | 126 | view.setNeedsLayout() 127 | view.layoutIfNeeded() 128 | 129 | UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 1, options: UIViewAnimationOptions.CurveEaseInOut, animations: { 130 | 131 | toastTopConstraint.updateOffset(-toast.frame.size.height) 132 | self.view.setNeedsLayout() 133 | self.view.layoutIfNeeded() 134 | 135 | }) { (finished) in 136 | let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(2 * Double(NSEC_PER_SEC))) 137 | 138 | dispatch_after(delayTime, dispatch_get_main_queue()) { 139 | self.hideErrorToast(toast) 140 | } 141 | } 142 | } 143 | 144 | func dismissToastOnTap(gesture: UITapGestureRecognizer) { 145 | if gesture.state == UIGestureRecognizerState.Recognized { 146 | hideErrorToast(gesture.view as! ErrorToastView) 147 | } 148 | } 149 | 150 | private func hideErrorToast(toast: ErrorToastView){ 151 | var frame = toast.frame 152 | UIView.animateWithDuration(0.25, animations: { 153 | frame.origin.y = self.view.frame.size.height 154 | toast.frame = frame 155 | }) { (finished: Bool) in 156 | toast.removeFromSuperview() 157 | self.navigationItem.rightBarButtonItem?.enabled = true 158 | } 159 | } 160 | 161 | override public func didReceiveMemoryWarning() { 162 | super.didReceiveMemoryWarning() 163 | // Dispose of any resources that can be recreated. 164 | } 165 | 166 | } 167 | 168 | public extension PredicateEditorViewController { 169 | public func predicates() throws -> [NSPredicate] { 170 | let predicates = try sections.map({ (section) -> NSPredicate in 171 | return try section.compoundPredicate() 172 | }) 173 | 174 | return predicates.filter({ (predicate:NSPredicate) -> Bool in 175 | return !predicate.isEmpty 176 | }) 177 | } 178 | } 179 | 180 | -------------------------------------------------------------------------------- /Example/Pods/SeedStackViewController/README.md: -------------------------------------------------------------------------------- 1 | # StackViewController 2 | [![Circle CI](https://circleci.com/gh/seedco/StackViewController/tree/master.svg?style=svg)](https://circleci.com/gh/seedco/StackViewController/tree/master) 3 | 4 | ### Overview 5 | 6 | `StackViewController` is a Swift framework that simplifies the process of building forms and other static content using `UIStackView`. For example, the form below is implemented using a StackViewController: 7 | 8 |

9 | StackViewController Example App 10 |

11 | 12 | ### Design Rationale 13 | 14 | The purpose of this project is two-fold: encouraging design patterns that are more suitable for building content like the form pictured above, and providing tools to make the process simpler. The following sections contain a summary of the existing solutions and how we can improve upon them. 15 | 16 | #### Building Forms with `UITableView` (Is Difficult) 17 | 18 | Traditionally, iOS developers have utilized `UITableView` to build forms and other relatively static list-based user interfaces, despite the `UITableView` API being a poor fit for such tasks. `UITableView` is designed primarily for dynamic content, and a lot of the functionality that it provides is *only necessary* for dynamic content. Using it to build static user interfaces results in a lot of boilerplate code in implementing many data source and delegate methods. 19 | 20 | Another major issue is the difficulty of implementing variable-height content with `UITableView`. When building a form, for example, a common need is the ability to display a field (e.g. a text view) whose dimensions automatically change as the content inside it changes. One half of the problem is knowing how to size the cell — this is typically done by either manually computing the size in `-tableView:heightForRowAtIndexPath:` or by using Autolayout, estimated row heights, and the self-sizing table view cell feature introduced in iOS 8. The other half of the problem is notifying the table view that it should update the layout for a cell once the content inside the cell changes. This can involve ugly hacks like calling `-[UITableView beginUpdates]` and `-[UITableView endUpdates]` to force relayout. 21 | 22 | The bottom line is that **`UITableView` is the wrong tool for the job**. 23 | 24 | #### Introducing `UIStackView` 25 | 26 | [`UIStackView`](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIStackView_Class_Reference/), introduced in iOS 9, provides a clean abstraction over Autolayout for laying out a horizontal or vertical stack of views. By composing multiple instances of `UIStackView`, the vast majority of common user interface layouts can be built quite easily without the need to manually create and remove layout constraints. 27 | 28 | `UIStackView` is well suited for the task of building forms and other static content, but it has some shortcomings when applied to that particular use case. There are things that `UITableView` and `UITableViewController` provide that we often take for granted: scrolling support, cell separators, and other conveniences. `UIStackView` doesn't have this functionality built in, so one of the goals of this library is to fill in those key pieces of missing functionality to the point where using a stack view is *easier* than using a table view for the same task. 29 | 30 | #### View Controllers over Views 31 | 32 | A strong indicator of poorly designed iOS code is a bad separation of responsibilities between the view and the view controller, in accordance with the MVC (Model-View-Controller) pattern. The *Massive View Controller* anti-pattern is a common occurrence where the view controller simply does too much, absorbing responsibilities from the model and view layers. Conversely, there is also an anti-pattern where the view takes on many controller-like responsibilities rather than just focusing on the layout and rendering of the content. 33 | 34 | `StackViewController` defines a **single** API for using both `UIView` and `UIViewController` instances to provide content. `UIView` instances can be used when the content being displayed is simple and non-interactive (e.g. a static label). `UIViewController` instances can be used for more complex controls where there needs to be a controller in addition to the view, when, for example, a view displays a visual representation of state from a model that needs to be updated as the user interacts with the view. 35 | 36 | #### View Controller Composition 37 | 38 | [*Composition over inheritance*](https://en.wikipedia.org/wiki/Composition_over_inheritance) is a fundamental principle of object-oriented programming. 39 | 40 | This principle has always been used in iOS view hierarchies, where more complex views are composed out of simpler ones (e.g. how a `UIButton` contains a `UILabel` and a `UIImageView` that render its content). However, there was no "official" way to compose view controllers until the introduction of [view controller containment](https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html) in iOS 5. It was possible to mimic behaviour like this prior to iOS 5, but handling the propagation of events between parent and child view controllers and transitions between child view controllers was difficult to get right, which are all problems that the view controller containment API solves. 41 | 42 | In the same way that you can create complex layouts by composing multiple `UIStackView` instances, you can use the view controller containment API to compose multiple instances of `StackViewController` to create a hierarchy of view controllers where each content view is backed by a corresponding view controller that cleanly separates the responsibilities, instead of handling all of that at the view level (an anti-pattern, as mentioned earlier). 43 | 44 | ### Features 45 | 46 | The framework provides two primary classes: `StackViewContainer` and `StackViewController`. `StackViewContainer` wraps a `UIStackView` and implements the following additional features: 47 | 48 | * **Scrolling support** by embedding the `UIStackView` inside a `UIScrollView` with automatic management of associated constraints 49 | * **Autoscroll behaviour** to automatically adjust layout and scroll to the view being edited when the keyboard appears (the same behaviour implemented by `UITableViewController`) 50 | * **Customizable separator views** between content views that can be toggled on a per-view basis and are managed automatically when content views are inserted and removed 51 | * Other minor conveniences like support for background views and changing the background color (since `UIStackView` doesn't draw a background) 52 | 53 | `StackViewController` is a subclass of `UIViewController` that uses an instance of `StackViewContainer` as its view, and adds support for adding content using [view controller containment](https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html) (i.e. view controller composition). This means that you can use view controllers and/or views to represent your content instead of just views, and `StackViewController` automatically handles adding and removing them as child view controllers. 54 | 55 | ### Example 56 | 57 | The included example app, pictured above, demonstrates the usage of both `StackViewContainer` on its own (the image attachment control) as well as `StackViewController` (the full form). 58 | 59 | ### License 60 | 61 | This project is licensed under the MIT license. See `LICENSE.md` for more details. 62 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/Debugging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | /** 31 | Used to allow adding a snp_label to a View for debugging purposes 32 | */ 33 | public extension View { 34 | 35 | public var snp_label: String? { 36 | get { 37 | return objc_getAssociatedObject(self, &labelKey) as? String 38 | } 39 | set { 40 | objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC) 41 | } 42 | } 43 | 44 | } 45 | 46 | /** 47 | Used to allow adding a snp_label to a LayoutConstraint for debugging purposes 48 | */ 49 | public extension LayoutConstraint { 50 | 51 | public var snp_label: String? { 52 | get { 53 | return objc_getAssociatedObject(self, &labelKey) as? String 54 | } 55 | set { 56 | objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC) 57 | } 58 | } 59 | 60 | override public var description: String { 61 | var description = "<" 62 | 63 | description += descriptionForObject(self) 64 | 65 | if let firstItem: AnyObject = self.firstItem { 66 | description += " \(descriptionForObject(firstItem))" 67 | } 68 | 69 | if self.firstAttribute != .NotAnAttribute { 70 | description += ".\(self.firstAttribute.snp_description)" 71 | } 72 | 73 | description += " \(self.relation.snp_description)" 74 | 75 | if let secondItem: AnyObject = self.secondItem { 76 | description += " \(descriptionForObject(secondItem))" 77 | } 78 | 79 | if self.secondAttribute != .NotAnAttribute { 80 | description += ".\(self.secondAttribute.snp_description)" 81 | } 82 | 83 | if self.multiplier != 1.0 { 84 | description += " * \(self.multiplier)" 85 | } 86 | 87 | if self.secondAttribute == .NotAnAttribute { 88 | description += " \(self.constant)" 89 | } else { 90 | if self.constant > 0.0 { 91 | description += " + \(self.constant)" 92 | } else if self.constant < 0.0 { 93 | description += " - \(CGFloat.abs(self.constant))" 94 | } 95 | } 96 | 97 | if self.priority != 1000.0 { 98 | description += " ^\(self.priority)" 99 | } 100 | 101 | description += ">" 102 | 103 | return description 104 | } 105 | 106 | internal var snp_makerFile: String? { 107 | return self.snp_constraint?.makerFile 108 | } 109 | 110 | internal var snp_makerLine: UInt? { 111 | return self.snp_constraint?.makerLine 112 | } 113 | 114 | } 115 | 116 | private var labelKey = "" 117 | 118 | private func descriptionForObject(object: AnyObject) -> String { 119 | let pointerDescription = NSString(format: "%p", ObjectIdentifier(object).uintValue) 120 | var desc = "" 121 | 122 | desc += object.dynamicType.description() 123 | 124 | if let object = object as? View { 125 | desc += ":\(object.snp_label ?? pointerDescription)" 126 | } else if let object = object as? LayoutConstraint { 127 | desc += ":\(object.snp_label ?? pointerDescription)" 128 | } else { 129 | desc += ":\(pointerDescription)" 130 | } 131 | 132 | if let object = object as? LayoutConstraint, let file = object.snp_makerFile, let line = object.snp_makerLine { 133 | desc += "@\(file)#\(line)" 134 | } 135 | 136 | desc += "" 137 | return desc 138 | } 139 | 140 | private extension NSLayoutRelation { 141 | 142 | private var snp_description: String { 143 | switch self { 144 | case .Equal: return "==" 145 | case .GreaterThanOrEqual: return ">=" 146 | case .LessThanOrEqual: return "<=" 147 | } 148 | } 149 | 150 | } 151 | 152 | private extension NSLayoutAttribute { 153 | 154 | private var snp_description: String { 155 | #if os(iOS) || os(tvOS) 156 | switch self { 157 | case .NotAnAttribute: return "notAnAttribute" 158 | case .Top: return "top" 159 | case .Left: return "left" 160 | case .Bottom: return "bottom" 161 | case .Right: return "right" 162 | case .Leading: return "leading" 163 | case .Trailing: return "trailing" 164 | case .Width: return "width" 165 | case .Height: return "height" 166 | case .CenterX: return "centerX" 167 | case .CenterY: return "centerY" 168 | case .LastBaseline: return "baseline" 169 | case .FirstBaseline: return "firstBaseline" 170 | case .TopMargin: return "topMargin" 171 | case .LeftMargin: return "leftMargin" 172 | case .BottomMargin: return "bottomMargin" 173 | case .RightMargin: return "rightMargin" 174 | case .LeadingMargin: return "leadingMargin" 175 | case .TrailingMargin: return "trailingMargin" 176 | case .CenterXWithinMargins: return "centerXWithinMargins" 177 | case .CenterYWithinMargins: return "centerYWithinMargins" 178 | } 179 | #else 180 | switch self { 181 | case .NotAnAttribute: return "notAnAttribute" 182 | case .Top: return "top" 183 | case .Left: return "left" 184 | case .Bottom: return "bottom" 185 | case .Right: return "right" 186 | case .Leading: return "leading" 187 | case .Trailing: return "trailing" 188 | case .Width: return "width" 189 | case .Height: return "height" 190 | case .CenterX: return "centerX" 191 | case .CenterY: return "centerY" 192 | case .LastBaseline: return "baseline" 193 | default: return "default" 194 | } 195 | #endif 196 | 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /PredicateEditor/Classes/Row.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Arvindh Sukumar on 07/07/16. 3 | // 4 | 5 | import Foundation 6 | 7 | enum RowPredicateError: ErrorType { 8 | case InsufficientData(keyPath: KeyPathDescriptor?) 9 | case InvalidComparisonType(keyPath: String) 10 | } 11 | 12 | let valueDateFormatter: NSDateFormatter = { 13 | let df = NSDateFormatter() 14 | df.dateStyle = NSDateFormatterStyle.ShortStyle 15 | return df 16 | }() 17 | 18 | let valueTimeFormatter: NSDateFormatter = { 19 | let df = NSDateFormatter() 20 | df.dateStyle = NSDateFormatterStyle.NoStyle 21 | df.timeStyle = NSDateFormatterStyle.ShortStyle 22 | return df 23 | }() 24 | 25 | let valueDateTimeFormatter: NSDateFormatter = { 26 | let df = NSDateFormatter() 27 | df.dateStyle = NSDateFormatterStyle.ShortStyle 28 | df.timeStyle = NSDateFormatterStyle.ShortStyle 29 | return df 30 | }() 31 | 32 | @objc public class Row: NSObject { 33 | public var descriptor: KeyPathDescriptor? 34 | public var comparisonType: KeyPathComparisonType? 35 | public var value: PredicateComparable? 36 | var stringValue: String? { 37 | get { 38 | return baseValueToString() 39 | } 40 | set { 41 | value = stringValueToBase(newValue) 42 | } 43 | } 44 | weak var section: Section? 45 | public var index: Int? { 46 | return section?.rows.indexOf(self) 47 | } 48 | 49 | required convenience public init?(descriptor: KeyPathDescriptor, comparisonType: KeyPathComparisonType, value: PredicateComparable?) { 50 | if !descriptor.propertyType.comparisonTypes().contains(comparisonType){ 51 | return nil 52 | } 53 | self.init() 54 | self.descriptor = descriptor 55 | self.comparisonType = comparisonType 56 | self.value = value 57 | } 58 | 59 | func stringValueToBase(string: String?) -> PredicateComparable? { 60 | guard let descriptor = descriptor, comparisonType = comparisonType, let stringValue = string else { 61 | return nil 62 | } 63 | 64 | var returnValue: PredicateComparable? 65 | 66 | let propertyType = descriptor.propertyType 67 | switch propertyType { 68 | case .String: 69 | returnValue = stringValue 70 | case .Int: 71 | returnValue = Int(stringValue) 72 | case .Float: 73 | returnValue = Float(stringValue) 74 | case .Double: 75 | returnValue = Double(stringValue) 76 | case .Boolean: 77 | returnValue = Bool.fromString(stringValue) 78 | case .Date: 79 | returnValue = valueDateFormatter.dateFromString(stringValue) 80 | case .Time: 81 | returnValue = valueTimeFormatter.dateFromString(stringValue) 82 | case .DateTime: 83 | returnValue = valueDateTimeFormatter.dateFromString(stringValue) 84 | default: 85 | break 86 | } 87 | return returnValue 88 | } 89 | 90 | func baseValueToString() -> String? { 91 | guard let descriptor = descriptor, comparisonType = comparisonType, let value = value else { 92 | return nil 93 | } 94 | 95 | if let string = value as? String { 96 | return string 97 | } 98 | if let date = value as? NSDate { 99 | switch descriptor.propertyType { 100 | case .Date: 101 | return valueDateFormatter.stringFromDate(date) 102 | case .Time: 103 | return valueTimeFormatter.stringFromDate(date) 104 | case .DateTime: 105 | return valueDateTimeFormatter.stringFromDate(date) 106 | default: 107 | return nil 108 | } 109 | } 110 | if let bool = value as? Bool { 111 | return bool.toString() 112 | } 113 | if let stringConvertible = value as? CustomStringConvertible { 114 | return String(stringConvertible) 115 | } 116 | return nil 117 | } 118 | 119 | func resetBaseValue() { 120 | value = stringValueToBase(stringValue) 121 | } 122 | 123 | func toPredicate() throws -> NSPredicate { 124 | guard let descriptor = descriptor, comparisonType = comparisonType, let value = value else { 125 | throw RowPredicateError.InsufficientData(keyPath: self.descriptor) 126 | } 127 | 128 | if !descriptor.propertyType.comparisonTypes().contains(comparisonType) { 129 | throw RowPredicateError.InvalidComparisonType(keyPath: descriptor.keyPath) 130 | } 131 | 132 | var predicate: NSPredicate! 133 | if let customPredicate = customPredicate(descriptor, comparison: comparisonType, arg: value){ 134 | predicate = customPredicate 135 | } 136 | else { 137 | let lhsExpression = NSExpression(forKeyPath: descriptor.keyPath) 138 | let rhsExpression = NSExpression(forConstantValue: value.constantValue()) 139 | 140 | var type: NSPredicateOperatorType = comparisonType.predicateOperatorType()! 141 | var options: NSComparisonPredicateOptions = (descriptor.propertyType == .String) ? [NSComparisonPredicateOptions.CaseInsensitivePredicateOption, NSComparisonPredicateOptions.DiacriticInsensitivePredicateOption] : [] 142 | 143 | predicate = NSComparisonPredicate(leftExpression: lhsExpression, 144 | rightExpression: rhsExpression, 145 | modifier: NSComparisonPredicateModifier.DirectPredicateModifier, 146 | type: type, 147 | options: options) 148 | } 149 | return comparisonType.shouldNegate() ? NSCompoundPredicate(notPredicateWithSubpredicate: predicate) : predicate 150 | } 151 | 152 | func customPredicate(keyPathDescriptor: KeyPathDescriptor, comparison: KeyPathComparisonType, arg: PredicateComparable?) -> NSPredicate? { 153 | let keyPath = keyPathDescriptor.keyPath 154 | let constantValue = arg?.constantValue() 155 | 156 | switch comparison { 157 | case .IsOn, .IsNotOn: 158 | let date = constantValue as? NSDate 159 | return NSPredicate(format: "%K.beginningOfDay == %@", keyPath, date?.beginningOfDay ?? NSNull()) 160 | case .IsExactly, .IsNotExactly: 161 | let date = constantValue as? NSDate 162 | switch keyPathDescriptor.propertyType { 163 | case .DateTime: 164 | return NSPredicate(format: "%K == %@", keyPath, date ?? NSNull()) 165 | case .Time: 166 | return NSPredicate(format: "%K.time == %@", keyPath, date?.time ?? NSNull()) 167 | default: 168 | return nil 169 | } 170 | case .IsAfter: 171 | let date = constantValue as? NSDate 172 | switch keyPathDescriptor.propertyType { 173 | case .Date: 174 | return NSPredicate(format: "%K.endOfDay < %@", keyPath, date?.beginningOfDay ?? NSNull()) 175 | case .Time: 176 | return NSPredicate(format: "%K.time > %@", keyPath, date?.time ?? NSNull()) 177 | case .DateTime: 178 | return NSPredicate(format: "%K > %@", keyPath, date ?? NSNull()) 179 | default: 180 | return nil 181 | } 182 | case .IsBefore: 183 | let date = constantValue as? NSDate 184 | switch keyPathDescriptor.propertyType { 185 | case .Date: 186 | return NSPredicate(format: "%K.beginningOfDay > %@", keyPath, date?.endOfDay ?? NSNull()) 187 | case .Time: 188 | return NSPredicate(format: "%K.time < %@", keyPath, date?.time ?? NSNull()) 189 | case .DateTime: 190 | return NSPredicate(format: "%K < %@", keyPath, date ?? NSNull()) 191 | default: 192 | return nil 193 | } 194 | case .IsToday: 195 | let date = constantValue as? NSDate 196 | return NSPredicate(format: "%K.today == %@", keyPath, NSDate.today()) 197 | default: 198 | return nil 199 | } 200 | } 201 | 202 | } 203 | 204 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/ConstraintAttributes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | #else 27 | import AppKit 28 | #endif 29 | 30 | /** 31 | Used to define `NSLayoutAttributes` in a more concise and composite manner 32 | */ 33 | internal struct ConstraintAttributes: OptionSetType, BooleanType { 34 | 35 | internal init(rawValue: UInt) { 36 | self.rawValue = rawValue 37 | } 38 | internal init(_ rawValue: UInt) { 39 | self.init(rawValue: rawValue) 40 | } 41 | internal init(nilLiteral: ()) { 42 | self.rawValue = 0 43 | } 44 | 45 | internal private(set) var rawValue: UInt 46 | internal static var allZeros: ConstraintAttributes { return self.init(0) } 47 | internal static func convertFromNilLiteral() -> ConstraintAttributes { return self.init(0) } 48 | internal var boolValue: Bool { return self.rawValue != 0 } 49 | 50 | internal func toRaw() -> UInt { return self.rawValue } 51 | internal static func fromRaw(raw: UInt) -> ConstraintAttributes? { return self.init(raw) } 52 | internal static func fromMask(raw: UInt) -> ConstraintAttributes { return self.init(raw) } 53 | 54 | // normal 55 | 56 | internal static var None: ConstraintAttributes { return self.init(0) } 57 | internal static var Left: ConstraintAttributes { return self.init(1) } 58 | internal static var Top: ConstraintAttributes { return self.init(2) } 59 | internal static var Right: ConstraintAttributes { return self.init(4) } 60 | internal static var Bottom: ConstraintAttributes { return self.init(8) } 61 | internal static var Leading: ConstraintAttributes { return self.init(16) } 62 | internal static var Trailing: ConstraintAttributes { return self.init(32) } 63 | internal static var Width: ConstraintAttributes { return self.init(64) } 64 | internal static var Height: ConstraintAttributes { return self.init(128) } 65 | internal static var CenterX: ConstraintAttributes { return self.init(256) } 66 | internal static var CenterY: ConstraintAttributes { return self.init(512) } 67 | internal static var Baseline: ConstraintAttributes { return self.init(1024) } 68 | 69 | @available(iOS 8.0, *) 70 | internal static var FirstBaseline: ConstraintAttributes { return self.init(2048) } 71 | @available(iOS 8.0, *) 72 | internal static var LeftMargin: ConstraintAttributes { return self.init(4096) } 73 | @available(iOS 8.0, *) 74 | internal static var RightMargin: ConstraintAttributes { return self.init(8192) } 75 | @available(iOS 8.0, *) 76 | internal static var TopMargin: ConstraintAttributes { return self.init(16384) } 77 | @available(iOS 8.0, *) 78 | internal static var BottomMargin: ConstraintAttributes { return self.init(32768) } 79 | @available(iOS 8.0, *) 80 | internal static var LeadingMargin: ConstraintAttributes { return self.init(65536) } 81 | @available(iOS 8.0, *) 82 | internal static var TrailingMargin: ConstraintAttributes { return self.init(131072) } 83 | @available(iOS 8.0, *) 84 | internal static var CenterXWithinMargins: ConstraintAttributes { return self.init(262144) } 85 | @available(iOS 8.0, *) 86 | internal static var CenterYWithinMargins: ConstraintAttributes { return self.init(524288) } 87 | 88 | // aggregates 89 | 90 | internal static var Edges: ConstraintAttributes { return self.init(15) } 91 | internal static var Size: ConstraintAttributes { return self.init(192) } 92 | internal static var Center: ConstraintAttributes { return self.init(768) } 93 | 94 | @available(iOS 8.0, *) 95 | internal static var Margins: ConstraintAttributes { return self.init(61440) } 96 | 97 | @available(iOS 8.0, *) 98 | internal static var CenterWithinMargins: ConstraintAttributes { return self.init(786432) } 99 | 100 | internal var layoutAttributes:[NSLayoutAttribute] { 101 | var attrs = [NSLayoutAttribute]() 102 | if (self.contains(ConstraintAttributes.Left)) { 103 | attrs.append(.Left) 104 | } 105 | if (self.contains(ConstraintAttributes.Top)) { 106 | attrs.append(.Top) 107 | } 108 | if (self.contains(ConstraintAttributes.Right)) { 109 | attrs.append(.Right) 110 | } 111 | if (self.contains(ConstraintAttributes.Bottom)) { 112 | attrs.append(.Bottom) 113 | } 114 | if (self.contains(ConstraintAttributes.Leading)) { 115 | attrs.append(.Leading) 116 | } 117 | if (self.contains(ConstraintAttributes.Trailing)) { 118 | attrs.append(.Trailing) 119 | } 120 | if (self.contains(ConstraintAttributes.Width)) { 121 | attrs.append(.Width) 122 | } 123 | if (self.contains(ConstraintAttributes.Height)) { 124 | attrs.append(.Height) 125 | } 126 | if (self.contains(ConstraintAttributes.CenterX)) { 127 | attrs.append(.CenterX) 128 | } 129 | if (self.contains(ConstraintAttributes.CenterY)) { 130 | attrs.append(.CenterY) 131 | } 132 | if (self.contains(ConstraintAttributes.Baseline)) { 133 | #if swift(>=2.3) 134 | attrs.append(.LastBaseline) 135 | #else 136 | attrs.append(.Baseline) 137 | #endif 138 | } 139 | 140 | #if os(iOS) || os(tvOS) 141 | #if SNAPKIT_DEPLOYMENT_LEGACY 142 | guard #available(iOS 8.0, *) else { 143 | return attrs 144 | } 145 | #endif 146 | if (self.contains(ConstraintAttributes.FirstBaseline)) { 147 | attrs.append(.FirstBaseline) 148 | } 149 | if (self.contains(ConstraintAttributes.LeftMargin)) { 150 | attrs.append(.LeftMargin) 151 | } 152 | if (self.contains(ConstraintAttributes.RightMargin)) { 153 | attrs.append(.RightMargin) 154 | } 155 | if (self.contains(ConstraintAttributes.TopMargin)) { 156 | attrs.append(.TopMargin) 157 | } 158 | if (self.contains(ConstraintAttributes.BottomMargin)) { 159 | attrs.append(.BottomMargin) 160 | } 161 | if (self.contains(ConstraintAttributes.LeadingMargin)) { 162 | attrs.append(.LeadingMargin) 163 | } 164 | if (self.contains(ConstraintAttributes.TrailingMargin)) { 165 | attrs.append(.TrailingMargin) 166 | } 167 | if (self.contains(ConstraintAttributes.CenterXWithinMargins)) { 168 | attrs.append(.CenterXWithinMargins) 169 | } 170 | if (self.contains(ConstraintAttributes.CenterYWithinMargins)) { 171 | attrs.append(.CenterYWithinMargins) 172 | } 173 | #endif 174 | 175 | return attrs 176 | } 177 | } 178 | internal func +=(inout left: ConstraintAttributes, right: ConstraintAttributes) { 179 | left.unionInPlace(right) 180 | } 181 | internal func -=(inout left: ConstraintAttributes, right: ConstraintAttributes) { 182 | left.subtractInPlace(right) 183 | } 184 | internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool { 185 | return left.rawValue == right.rawValue 186 | } 187 | -------------------------------------------------------------------------------- /Example/Pods/SnapKit/Source/View+SnapKit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnapKit 3 | // 4 | // Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | #if os(iOS) || os(tvOS) 25 | import UIKit 26 | public typealias View = UIView 27 | #else 28 | import AppKit 29 | public typealias View = NSView 30 | #endif 31 | 32 | /** 33 | Used to expose public API on views 34 | */ 35 | public extension View { 36 | 37 | /// left edge 38 | public var snp_left: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Left) } 39 | 40 | /// top edge 41 | public var snp_top: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Top) } 42 | 43 | /// right edge 44 | public var snp_right: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Right) } 45 | 46 | /// bottom edge 47 | public var snp_bottom: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Bottom) } 48 | 49 | /// leading edge 50 | public var snp_leading: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Leading) } 51 | 52 | /// trailing edge 53 | public var snp_trailing: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Trailing) } 54 | 55 | /// width dimension 56 | public var snp_width: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Width) } 57 | 58 | /// height dimension 59 | public var snp_height: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Height) } 60 | 61 | /// centerX position 62 | public var snp_centerX: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterX) } 63 | 64 | /// centerY position 65 | public var snp_centerY: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterY) } 66 | 67 | /// baseline position 68 | public var snp_baseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Baseline) } 69 | 70 | /// first baseline position 71 | @available(iOS 8.0, *) 72 | public var snp_firstBaseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.FirstBaseline) } 73 | 74 | /// left margin 75 | @available(iOS 8.0, *) 76 | public var snp_leftMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeftMargin) } 77 | 78 | /// right margin 79 | @available(iOS 8.0, *) 80 | public var snp_rightMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.RightMargin) } 81 | 82 | /// top margin 83 | @available(iOS 8.0, *) 84 | public var snp_topMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TopMargin) } 85 | 86 | /// bottom margin 87 | @available(iOS 8.0, *) 88 | public var snp_bottomMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.BottomMargin) } 89 | 90 | /// leading margin 91 | @available(iOS 8.0, *) 92 | public var snp_leadingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeadingMargin) } 93 | 94 | /// trailing margin 95 | @available(iOS 8.0, *) 96 | public var snp_trailingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TrailingMargin) } 97 | 98 | /// centerX within margins 99 | @available(iOS 8.0, *) 100 | public var snp_centerXWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterXWithinMargins) } 101 | 102 | /// centerY within margins 103 | @available(iOS 8.0, *) 104 | public var snp_centerYWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterYWithinMargins) } 105 | 106 | // top + left + bottom + right edges 107 | public var snp_edges: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Edges) } 108 | 109 | // width + height dimensions 110 | public var snp_size: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Size) } 111 | 112 | // centerX + centerY positions 113 | public var snp_center: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Center) } 114 | 115 | // top + left + bottom + right margins 116 | @available(iOS 8.0, *) 117 | public var snp_margins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Margins) } 118 | 119 | // centerX + centerY within margins 120 | @available(iOS 8.0, *) 121 | public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) } 122 | 123 | /** 124 | Prepares constraints with a `ConstraintMaker` and returns the made constraints but does not install them. 125 | 126 | - parameter closure that will be passed the `ConstraintMaker` to make the constraints with 127 | 128 | - returns: the constraints made 129 | */ 130 | public func snp_prepareConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> [Constraint] { 131 | return ConstraintMaker.prepareConstraints(view: self, file: file, line: line, closure: closure) 132 | } 133 | 134 | /** 135 | Makes constraints with a `ConstraintMaker` and installs them along side any previous made constraints. 136 | 137 | - parameter closure that will be passed the `ConstraintMaker` to make the constraints with 138 | */ 139 | public func snp_makeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void { 140 | ConstraintMaker.makeConstraints(view: self, file: file, line: line, closure: closure) 141 | } 142 | 143 | /** 144 | Updates constraints with a `ConstraintMaker` that will replace existing constraints that match and install new ones. 145 | 146 | For constraints to match only the constant can be updated. 147 | 148 | - parameter closure that will be passed the `ConstraintMaker` to update the constraints with 149 | */ 150 | public func snp_updateConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void { 151 | ConstraintMaker.updateConstraints(view: self, file: file, line: line, closure: closure) 152 | } 153 | 154 | /** 155 | Remakes constraints with a `ConstraintMaker` that will first remove all previously made constraints and make and install new ones. 156 | 157 | - parameter closure that will be passed the `ConstraintMaker` to remake the constraints with 158 | */ 159 | public func snp_remakeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void { 160 | ConstraintMaker.remakeConstraints(view: self, file: file, line: line, closure: closure) 161 | } 162 | 163 | /** 164 | Removes all previously made constraints. 165 | */ 166 | public func snp_removeConstraints() { 167 | ConstraintMaker.removeConstraints(view: self) 168 | } 169 | 170 | internal var snp_installedLayoutConstraints: [LayoutConstraint] { 171 | get { 172 | if let constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? [LayoutConstraint] { 173 | return constraints 174 | } 175 | return [] 176 | } 177 | set { 178 | objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 179 | } 180 | } 181 | } 182 | 183 | private var installedLayoutConstraintsKey = "" 184 | --------------------------------------------------------------------------------