From 75f2a98d5d7aeabba57b4aa0fc6eb377cb1f548e Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 30 Mar 2015 23:42:59 +0100 Subject: [PATCH 01/71] [QuerySet] Fix issue with reverse --- QueryKit/QuerySet.swift | 6 +++++- QueryKitTests/QuerySetTests.swift | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index e95f44c..473abf4 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -59,7 +59,11 @@ public class QuerySet : SequenceType, Equatable { /// Reverses the ordering of the QuerySet public func reverse() -> QuerySet { - return QuerySet(queryset:self, sortDescriptors:sortDescriptors.reverse(), predicate:predicate, range:range) + func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { + return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) + } + + return QuerySet(queryset:self, sortDescriptors:map(sortDescriptors, reverseSortDescriptor), predicate:predicate, range:range) } // MARK: Filtering diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index e7efb08..c14028c 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -52,7 +52,10 @@ class QuerySetTests: XCTestCase { let ageSortDescriptor = NSSortDescriptor(key: "age", ascending: true) let qs = queryset.orderBy([nameSortDescriptor, ageSortDescriptor]).reverse() - XCTAssertEqual(qs.sortDescriptors, [ageSortDescriptor, nameSortDescriptor]) + XCTAssertEqual(qs.sortDescriptors, [ + NSSortDescriptor(key: "name", ascending: false), + NSSortDescriptor(key: "age", ascending: false), + ]) } // MARK: Filtering From 17ef6dbbd99ee6816e22cf966c6c37cf94195b26 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 30 Mar 2015 23:43:20 +0100 Subject: [PATCH 02/71] [QuerySet] Add a last counterpart to first --- QueryKit/QuerySet.swift | 10 ++++++++-- QueryKitTests/QuerySetTests.swift | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 473abf4..5f13968 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -132,14 +132,20 @@ public class QuerySet : SequenceType, Equatable { return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:fullRange) } } - + // Mark: Getters + public var first: T? { get { return self[0].object } } - + + public var last: T? { + get { + return reverse().first + } + } // MARK: Conversion diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index c14028c..f816f9b 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -151,11 +151,17 @@ class QuerySetTests: XCTestCase { } // MARK: Getters + func testFirst() { var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) XCTAssertEqual(qs.first!.name, "Ayaka") } + func testLast() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + XCTAssertEqual(qs.last!.name, "Scott") + } + // MARK: Conversion func testConversionToArray() { From b3dcd31cada6ae23e8b42f8b54523474e57ecdcb Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 30 Mar 2015 23:49:38 +0100 Subject: [PATCH 03/71] [README] Various Refactor --- README.md | 120 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 99fcd35..3ce3510 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,75 @@ -QueryKit -======== +# QueryKit [![Build Status](http://img.shields.io/travis/QueryKit/QueryKit/master.svg?style=flat)](https://travis-ci.org/QueryKit/QueryKit) -QueryKit, a simple CoreData query language. +QueryKit, a simple type-safe Core Data query language. -## Usage +## Installation + +```ruby +pod 'QueryKit' +``` + +## QuerySet + +A QuerySet represents a collection of objects from your Core Data Store. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. + +### Retrieving all objects ```swift -Person.queryset(context).filter(Person.name == "Kyle").delete() +QuerySet(context, "Person") ``` -### Querying +**NOTE**: *It’s recommend to implement a type type-safe `queryset` method on your model.* -To retrieve objects from CoreData with QueryKit, you can construct a QuerySet -for your model in a managed object context. +```swift +Person.queryset(context) +``` + +### Retrieving specific objects with filters -A queryset is an immutable object, any operation will return a new queryset -instead of modifying the queryset. +You can filter a QuerySet using the `filter` and `exclude` methods, which +accept a predicate and return a new QuerySet. ```swift -var queryset = Person.queryset(context) +queryset.filter(NSPredicate(format: "name == %@", "Kyle")) +queryset.exclude(NSPredicate(format: "age > 21")) ``` -#### Filtering +**NOTE**: *You can define [type-safe methods](https://github.com/QueryKit/TodoExample/blob/master/Todo/Model/Generated/_Task.swift#L14-26) on your models, or use the [mogenerator template](https://github.com/QueryKit/mogenerator-template) to generate these.* + +```swift +queryset.filter(Person.attributes.name == "Kyle") +queryset.exclude(Person.attributes.age > 21) +``` -You can filter a queryset using the `filter` and `exclude` methods, which -accept a predicate and return a new queryset. +#### Chaining filters + +The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example: + +```swift +queryset.filter(Person.attributes.name == "Kyle") + .exclude(Person.attributes.age > 21) + .filter(Person.attributes.isEmployed) +``` + +Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused. + +### QuerySets are lazy + +A QuerySet is lazy, creating a QuerySet doesn’t involve querying Core Data. QueryKit won’t actually execute the query until the QuerySet is *evaluated*. + +### Slicing + +Using slicing, you can limit your QuerySet to a certain number of results. ```swift -queryset.filter(NSPredicate(format:"name == %@", "Kyle")) -queryset.filter(Person.name == "Kyle") -queryset.exclude(Person.age < 21) -queryset.exclude(Person.isEmployed) +Person.queryset(context)[0..<10] ``` -#### Ordering +**NOTE**: *Remember, QuerySet’s are lazily evaluated. Slicing doesn’t evaluate the query.* + +### Ordering You can order a queryset's results by using the `orderBy` method which accepts a collection of sort descriptors: @@ -46,7 +80,7 @@ queryset.orderBy(Person.name.ascending) queryset.orderBy([Person.name.ascending, Person.age.descending]) ``` -#### Slicing +### Slicing You can use slicing to limit a queryset to a range. For example, to get the first 5 items: @@ -57,39 +91,47 @@ queryset[0..5] ### Fetching -#### Single object +#### Multiple objects + +A QuerySet is utterable, and it executes the query when you iterate over it. For example: ```swift -var kyle = queryset.filter(Person.name == "Kyle").get() +for person in queryset { + println("Hello \(person.name).") +} ``` -#### Object at index +You can also convert the QuerySet to an Array: ```swift -var orta = queryset[3] +queryset.array() ``` -#### Count +#### First object ```swift -queryset.count() +var kyle = Person.queryset(context).filter(Person.name == "Kyle").first ``` -#### Iteration +#### Last object ```swift -for person in queryset { - println(person.name) -} +var kyle = Person.queryset(context).filter(Person.name == "Kyle").last ``` -#### Conversion to an array +#### Object at index ```swift -queryset.array() +var orta = queryset[3] +``` + +#### Count + +```swift +queryset.count() ``` -### Deleting +#### Deleting This method immediately deletes the objects in your queryset and returns a count and an error if the operation failed. @@ -98,10 +140,9 @@ count and an error if the operation failed. queryset.delete() ``` -### Attributes +### Attribute -The `Attribute` is a generic structure for creating predicates providing -type-safety. +The `Attribute` is a generic structure for creating predicates in a type-safe manner. ```swift let name = Attribute("name") @@ -117,6 +158,8 @@ age << (22...30) #### Operators +The following types of comparisons are supported using Attribute: + | Comparison | Meaning | | ------- |:--------:| | == | x equals y | @@ -130,10 +173,9 @@ age << (22...30) | << | x IN y, where y is an array | | << | x BETWEEN y, where y is a range | -## Predicate extensions +### Predicate extensions -We've extended NSPredicate to add support for the `!`, `&&` and `||` operators -for joining predicates together. +We've also extended NSPredicate to add support for the `!`, `&&` and `||` operators for joining predicates together. ```swift NSPredicate(format:"name == Kyle") || NSPredicate(format:"name == Katie") From bbfdefcdcdd7407cdc9e56cdd8a467cbc46c45b5 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 31 Mar 2015 00:03:15 +0100 Subject: [PATCH 04/71] [README] Introduce usage section --- README.md | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3ce3510..da70de2 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,13 @@ QueryKit, a simple type-safe Core Data query language. pod 'QueryKit' ``` -## QuerySet +## Usage + +### QuerySet A QuerySet represents a collection of objects from your Core Data Store. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. -### Retrieving all objects +#### Retrieving all objects ```swift QuerySet(context, "Person") @@ -26,7 +28,7 @@ QuerySet(context, "Person") Person.queryset(context) ``` -### Retrieving specific objects with filters +#### Retrieving specific objects with filters You can filter a QuerySet using the `filter` and `exclude` methods, which accept a predicate and return a new QuerySet. @@ -43,7 +45,7 @@ queryset.filter(Person.attributes.name == "Kyle") queryset.exclude(Person.attributes.age > 21) ``` -#### Chaining filters +##### Chaining filters The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example: @@ -55,11 +57,11 @@ queryset.filter(Person.attributes.name == "Kyle") Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused. -### QuerySets are lazy +#### QuerySets are lazy A QuerySet is lazy, creating a QuerySet doesn’t involve querying Core Data. QueryKit won’t actually execute the query until the QuerySet is *evaluated*. -### Slicing +#### Slicing Using slicing, you can limit your QuerySet to a certain number of results. @@ -69,7 +71,7 @@ Person.queryset(context)[0..<10] **NOTE**: *Remember, QuerySet’s are lazily evaluated. Slicing doesn’t evaluate the query.* -### Ordering +#### Ordering You can order a queryset's results by using the `orderBy` method which accepts a collection of sort descriptors: @@ -80,7 +82,7 @@ queryset.orderBy(Person.name.ascending) queryset.orderBy([Person.name.ascending, Person.age.descending]) ``` -### Slicing +#### Slicing You can use slicing to limit a queryset to a range. For example, to get the first 5 items: @@ -89,9 +91,9 @@ first 5 items: queryset[0..5] ``` -### Fetching +#### Fetching -#### Multiple objects +##### Multiple objects A QuerySet is utterable, and it executes the query when you iterate over it. For example: @@ -107,31 +109,31 @@ You can also convert the QuerySet to an Array: queryset.array() ``` -#### First object +##### First object ```swift var kyle = Person.queryset(context).filter(Person.name == "Kyle").first ``` -#### Last object +##### Last object ```swift var kyle = Person.queryset(context).filter(Person.name == "Kyle").last ``` -#### Object at index +##### Object at index ```swift var orta = queryset[3] ``` -#### Count +##### Count ```swift queryset.count() ``` -#### Deleting +##### Deleting This method immediately deletes the objects in your queryset and returns a count and an error if the operation failed. @@ -140,7 +142,7 @@ count and an error if the operation failed. queryset.delete() ``` -### Attribute +#### Attribute The `Attribute` is a generic structure for creating predicates in a type-safe manner. @@ -156,7 +158,7 @@ age >= 25 age << (22...30) ``` -#### Operators +##### Operators The following types of comparisons are supported using Attribute: @@ -173,7 +175,7 @@ The following types of comparisons are supported using Attribute: | << | x IN y, where y is an array | | << | x BETWEEN y, where y is a range | -### Predicate extensions +#### Predicate extensions We've also extended NSPredicate to add support for the `!`, `&&` and `||` operators for joining predicates together. From 26f8d38c8123285b0463340d4ff746760b1ccd4e Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 31 Mar 2015 00:05:28 +0100 Subject: [PATCH 05/71] [podspec] Update description --- QueryKit.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 26a328c..9aaec2c 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' spec.version = '0.9.1' - spec.summary = 'A simple CoreData query language for Swift.' + spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } - spec.author = { 'Kyle Fuller' => 'inbox@kylefuller.co.uk' } - spec.social_media_url = 'http://twitter.com/kylefuller' + spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } + spec.social_media_url = 'http://twitter.com/QueryKit' spec.source = { :git => 'https://github.com/QueryKit/QueryKit.git', :tag => "#{spec.version}" } spec.source_files = 'QueryKit/QueryKit.h' spec.requires_arc = true From 1875b7928315f089dee094cf2baf814cedaae2d8 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 31 Mar 2015 00:15:24 +0100 Subject: [PATCH 06/71] [travis] We can now do a full pod spec lint --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e193ee2..12dfcf2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,5 +6,5 @@ script: - set -o pipefail - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c - - pod lib lint QueryKit.podspec --quick + - pod lib lint QueryKit.podspec From 80f9d6e1cc85f42d051c190851e0c93dc539dde1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Bu=CC=88gling?= Date: Fri, 3 Apr 2015 00:00:54 +0200 Subject: [PATCH 07/71] =?UTF-8?q?=C2=AF\=5F(=E3=83=84)=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppKit's `NSObject (NSDictionaryControllerKeyValuePair)` somehow messes with the `key` property of `NSSortDescriptor`. That seems to have no effect outside of the CP environment because the universal framework approach keeps AppKit out. Pretty hand-wavey 🌊,, but this works :) --- QueryKit/QuerySet.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 5f13968..9ebd122 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -9,6 +9,10 @@ import Foundation import CoreData +#if os(OSX) && COCOAPODS +import AppKit +#endif + /// Represents a lazy database lookup for a set of objects. public class QuerySet : SequenceType, Equatable { @@ -60,7 +64,11 @@ public class QuerySet : SequenceType, Equatable { /// Reverses the ordering of the QuerySet public func reverse() -> QuerySet { func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { + #if os(OSX) && COCOAPODS + return NSSortDescriptor(key: sortDescriptor.key()!, ascending: !sortDescriptor.ascending) + #else return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) + #endif } return QuerySet(queryset:self, sortDescriptors:map(sortDescriptors, reverseSortDescriptor), predicate:predicate, range:range) From 7205243a72eefc9b5eb5143eab3d0365ae62c676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Bu=CC=88gling?= Date: Thu, 2 Apr 2015 19:03:30 +0200 Subject: [PATCH 08/71] Fix ARCH definition for 32-bit. --- Configurations/UniversalFramework_Base.xcconfig | 2 +- QueryKit.xcodeproj/project.pbxproj | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Configurations/UniversalFramework_Base.xcconfig b/Configurations/UniversalFramework_Base.xcconfig index 4e8b5e9..b6fe0ab 100644 --- a/Configurations/UniversalFramework_Base.xcconfig +++ b/Configurations/UniversalFramework_Base.xcconfig @@ -9,7 +9,7 @@ // Make it universal SUPPORTED_PLATFORMS = iphonesimulator iphoneos macosx VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s -VALID_ARCHS[sdk=iphonesimulator*] = arm64 armv7 armv7s +VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 VALID_ARCHS[sdk=macosx*] = i386 x86_64 // Dynamic linking uses different default copy paths diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 73622be..1d49493 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -393,6 +393,7 @@ baseConfigurationReference = 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -448,6 +449,7 @@ baseConfigurationReference = 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; From 6be933359b418e82f4ae232ee88b9a66b2b9302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Bu=CC=88gling?= Date: Thu, 2 Apr 2015 19:02:10 +0200 Subject: [PATCH 09/71] Don't hard-code pointer size. Fixes #29 --- QueryKit/Attribute.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index d487f53..ea80104 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -40,7 +40,7 @@ public struct Attribute : Equatable { return NSExpression(forConstantValue: value as NSObject) } - if sizeof(value.dynamicType) == 8 { + if sizeof(value.dynamicType) == sizeof(uintptr_t) { let value = unsafeBitCast(value, Optional.self) if let value = value { return NSExpression(forConstantValue: value) From c3b309271b4572b845c0248957d45870229d8626 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 3 Apr 2015 00:04:31 +0100 Subject: [PATCH 10/71] Release 0.9.2 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 9aaec2c..d16f6f6 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.9.1' + spec.version = '0.9.2' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 03a4f59ef40e986fe355be8f7043e18d6ffe6d93 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 4 Apr 2015 22:25:03 +0100 Subject: [PATCH 11/71] Use 2 spaces for indentation --- QueryKit.xcodeproj/project.pbxproj | 6 +- QueryKit/Attribute.swift | 110 +++--- QueryKit/Expression.swift | 16 +- QueryKit/ObjectiveC/QKAttribute.h | 1 + QueryKit/ObjectiveC/QKAttribute.m | 260 ++++++------- QueryKit/ObjectiveC/QKAttribute.swift | 12 +- QueryKit/ObjectiveC/QKQuerySet.h | 2 +- QueryKit/ObjectiveC/QKQuerySet.m | 302 +++++++-------- QueryKit/ObjectiveC/QKQuerySet.swift | 34 +- QueryKit/Predicate.swift | 6 +- QueryKit/QueryKit.swift | 8 - QueryKit/QuerySet.swift | 346 +++++++++--------- QueryKitTests/AttributeTests.swift | 228 ++++++------ QueryKitTests/ExpressionTests.swift | 64 ++-- .../ObjectiveC/QKAttributeTests.swift | 108 +++--- QueryKitTests/ObjectiveC/QKQuerySetTests.m | 144 ++++---- .../ObjectiveC/QKQuerySetTests.swift | 38 +- QueryKitTests/QueryKitTests.swift | 44 +-- QueryKitTests/QuerySetTests.swift | 332 ++++++++--------- 19 files changed, 1026 insertions(+), 1035 deletions(-) delete mode 100644 QueryKit/QueryKit.swift diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 1d49493..6fcbca1 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 77A9B67F195374490016654E /* QueryKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A9B67E195374490016654E /* QueryKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 77A9B685195374490016654E /* QueryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77A9B679195374490016654E /* QueryKit.framework */; }; 77A9B68C195374490016654E /* QueryKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A9B68B195374490016654E /* QueryKitTests.swift */; }; - 77A9B698195374AA0016654E /* QueryKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A9B697195374AA0016654E /* QueryKit.swift */; }; 77B17B8519A94C9100D6540D /* QKAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 77B17B8319A94C9100D6540D /* QKAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; 77B17B8619A94C9100D6540D /* QKAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B17B8419A94C9100D6540D /* QKAttribute.m */; }; 77B17B8819A94D2C00D6540D /* QKAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B17B8719A94D2C00D6540D /* QKAttribute.swift */; }; @@ -77,7 +76,6 @@ 77A9B684195374490016654E /* QueryKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QueryKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 77A9B68A195374490016654E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 77A9B68B195374490016654E /* QueryKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryKitTests.swift; sourceTree = ""; }; - 77A9B697195374AA0016654E /* QueryKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryKit.swift; sourceTree = ""; }; 77B17B8319A94C9100D6540D /* QKAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QKAttribute.h; sourceTree = ""; }; 77B17B8419A94C9100D6540D /* QKAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKAttribute.m; sourceTree = ""; }; 77B17B8719A94D2C00D6540D /* QKAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKAttribute.swift; sourceTree = ""; }; @@ -129,7 +127,9 @@ 279294E41A4B4C60009C52E1 /* Configurations */, 77A9B67A195374490016654E /* Products */, ); + indentWidth = 2; sourceTree = ""; + tabWidth = 2; }; 77A9B67A195374490016654E /* Products */ = { isa = PBXGroup; @@ -144,7 +144,6 @@ isa = PBXGroup; children = ( 77A9B67E195374490016654E /* QueryKit.h */, - 77A9B697195374AA0016654E /* QueryKit.swift */, 77E3A05C1969C019009372A8 /* QuerySet.swift */, 77E8728019539C0900A6F13F /* Attribute.swift */, 77E3A0601969DDF5009372A8 /* Expression.swift */, @@ -325,7 +324,6 @@ 77E8728719539FD200A6F13F /* Predicate.swift in Sources */, 77B17B8619A94C9100D6540D /* QKAttribute.m in Sources */, 77B17B8819A94D2C00D6540D /* QKAttribute.swift in Sources */, - 77A9B698195374AA0016654E /* QueryKit.swift in Sources */, 77007D8319A95CE9007DC2BC /* QKQuerySet.swift in Sources */, 77007D8219A95CE9007DC2BC /* QKQuerySet.m in Sources */, 77E3A05D1969C019009372A8 /* QuerySet.swift in Sources */, diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index ea80104..f47c335 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -9,117 +9,117 @@ import Foundation public struct Attribute : Equatable { - public let name:String + public let name:String - public init(_ name:String) { - self.name = name - } + public init(_ name:String) { + self.name = name + } - /// Builds a compound attribute with other key paths - public init(attributes:Array) { - self.init(".".join(attributes)) - } + /// Builds a compound attribute with other key paths + public init(attributes:Array) { + self.init(".".join(attributes)) + } - public var expression:NSExpression { - return NSExpression(forKeyPath: name) - } + public var expression:NSExpression { + return NSExpression(forKeyPath: name) + } + + // MARK: Sorting - // MARK: Sorting + public func ascending() -> NSSortDescriptor { + return NSSortDescriptor(key: name, ascending: true) + } - public func ascending() -> NSSortDescriptor { - return NSSortDescriptor(key: name, ascending: true) + public func descending() -> NSSortDescriptor { + return NSSortDescriptor(key: name, ascending: false) + } + + func expressionForValue(value:T) -> NSExpression { + // TODO: Find a cleaner implementation + if let value = value as? NSObject { + return NSExpression(forConstantValue: value as NSObject) } - public func descending() -> NSSortDescriptor { - return NSSortDescriptor(key: name, ascending: false) + if sizeof(value.dynamicType) == sizeof(uintptr_t) { + let value = unsafeBitCast(value, Optional.self) + if let value = value { + return NSExpression(forConstantValue: value) + } } - func expressionForValue(value:T) -> NSExpression { - // TODO: Find a cleaner implementation - if let value = value as? NSObject { - return NSExpression(forConstantValue: value as NSObject) - } - - if sizeof(value.dynamicType) == sizeof(uintptr_t) { - let value = unsafeBitCast(value, Optional.self) - if let value = value { - return NSExpression(forConstantValue: value) - } - } - - let value = unsafeBitCast(value, Optional.self) - if let value = value { - return NSExpression(forConstantValue: value) - } - - return NSExpression(forConstantValue: NSNull()) + let value = unsafeBitCast(value, Optional.self) + if let value = value { + return NSExpression(forConstantValue: value) } + + return NSExpression(forConstantValue: NSNull()) + } } public func == (lhs: Attribute, rhs: Attribute) -> Bool { - return lhs.name == rhs.name + return lhs.name == rhs.name } public func == (left: Attribute, right: T) -> NSPredicate { - return left.expression == left.expressionForValue(right) + return left.expression == left.expressionForValue(right) } public func != (left: Attribute, right: T) -> NSPredicate { - return left.expression != left.expressionForValue(right) + return left.expression != left.expressionForValue(right) } public func > (left: Attribute, right: T) -> NSPredicate { - return left.expression > left.expressionForValue(right) + return left.expression > left.expressionForValue(right) } public func >= (left: Attribute, right: T) -> NSPredicate { - return left.expression >= left.expressionForValue(right) + return left.expression >= left.expressionForValue(right) } public func < (left: Attribute, right: T) -> NSPredicate { - return left.expression < left.expressionForValue(right) + return left.expression < left.expressionForValue(right) } public func <= (left: Attribute, right: T) -> NSPredicate { - return left.expression <= left.expressionForValue(right) + return left.expression <= left.expressionForValue(right) } public func ~= (left: Attribute, right: T) -> NSPredicate { - return left.expression ~= left.expressionForValue(right) + return left.expression ~= left.expressionForValue(right) } public func << (left: Attribute, right: [T]) -> NSPredicate { - return left.expression << NSExpression(forConstantValue: right._asCocoaArray()) + return left.expression << NSExpression(forConstantValue: right._asCocoaArray()) } public func << (left: Attribute, right: Range) -> NSPredicate { - let rightExpression = NSExpression(forConstantValue: [right.startIndex, right.endIndex]._asCocoaArray()) + let rightExpression = NSExpression(forConstantValue: [right.startIndex, right.endIndex]._asCocoaArray()) - return NSComparisonPredicate(leftExpression: left.expression, rightExpression: rightExpression, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.BetweenPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left.expression, rightExpression: rightExpression, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.BetweenPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } /// MARK: Bool Attributes prefix public func ! (left: Attribute) -> NSPredicate { - return left == false + return left == false } public extension QuerySet { - public func filter(attribute:Attribute) -> QuerySet { - return filter(attribute == true) - } + public func filter(attribute:Attribute) -> QuerySet { + return filter(attribute == true) + } - public func exclude(attribute:Attribute) -> QuerySet { - return filter(attribute == false) - } + public func exclude(attribute:Attribute) -> QuerySet { + return filter(attribute == false) + } } // MARK: Collections public func count(attribute:Attribute) -> Attribute { - return Attribute(attributes: [attribute.name, "@count"]) + return Attribute(attributes: [attribute.name, "@count"]) } public func count(attribute:Attribute) -> Attribute { - return Attribute(attributes: [attribute.name, "@count"]) + return Attribute(attributes: [attribute.name, "@count"]) } diff --git a/QueryKit/Expression.swift b/QueryKit/Expression.swift index ddd3630..6180570 100644 --- a/QueryKit/Expression.swift +++ b/QueryKit/Expression.swift @@ -9,33 +9,33 @@ import Foundation public func == (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func != (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func > (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func >= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func < (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func <= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func ~= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LikePredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LikePredicateOperatorType, options: NSComparisonPredicateOptions(0)) } public func << (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.InPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.InPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } diff --git a/QueryKit/ObjectiveC/QKAttribute.h b/QueryKit/ObjectiveC/QKAttribute.h index d388ff0..1f82b41 100644 --- a/QueryKit/ObjectiveC/QKAttribute.h +++ b/QueryKit/ObjectiveC/QKAttribute.h @@ -13,6 +13,7 @@ */ @interface QKAttribute : NSObject +/// The name for the attribute. @property (nonatomic, strong, readonly) NSString *name; /// Initialized the attribute from multiple other attributes diff --git a/QueryKit/ObjectiveC/QKAttribute.m b/QueryKit/ObjectiveC/QKAttribute.m index 2fce279..dc0910e 100644 --- a/QueryKit/ObjectiveC/QKAttribute.m +++ b/QueryKit/ObjectiveC/QKAttribute.m @@ -13,72 +13,72 @@ @implementation QKAttribute #pragma mark - NSCoding + (BOOL)supportsSecureCoding { - return YES; + return YES; } - (void)encodeWithCoder:(NSCoder *)encoder { - [encoder encodeObject:self.name forKey:@"name"]; + [encoder encodeObject:self.name forKey:@"name"]; } - (instancetype)initWithCoder:(NSCoder *)decoder { - NSString *name = [decoder decodeObjectOfClass:[NSString class] forKey:@"name"]; - return [self initWithName:name]; + NSString *name = [decoder decodeObjectOfClass:[NSString class] forKey:@"name"]; + return [self initWithName:name]; } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { - NSString *name = [self.name copyWithZone:zone]; - return [[[self class] alloc] initWithName:name]; + NSString *name = [self.name copyWithZone:zone]; + return [[[self class] alloc] initWithName:name]; } #pragma mark - - (instancetype)initWithAttributes:(QKAttribute *)attribute, ... { - NSParameterAssert(attribute != nil); + NSParameterAssert(attribute != nil); - NSMutableArray *attributes = [NSMutableArray arrayWithObject:attribute.name]; + NSMutableArray *attributes = [NSMutableArray arrayWithObject:attribute.name]; - va_list attributeList; - va_start(attributeList, attribute); - while ((attribute = va_arg(attributeList, id))) { - [attributes addObject:attribute.name]; - } - va_end(attributeList); + va_list attributeList; + va_start(attributeList, attribute); + while ((attribute = va_arg(attributeList, id))) { + [attributes addObject:attribute.name]; + } + va_end(attributeList); - NSString *name = [attributes componentsJoinedByString:@"."]; + NSString *name = [attributes componentsJoinedByString:@"."]; - if (self = [super init]) { - _name = name; - } + if (self = [super init]) { + _name = name; + } - return self; + return self; } - (instancetype)initWithName:(NSString *)name { - if (self = [super init]) { - _name = name; - } + if (self = [super init]) { + _name = name; + } - return self; + return self; } - (NSExpression *)expression { - return [NSExpression expressionForKeyPath:self.name]; + return [NSExpression expressionForKeyPath:self.name]; } #pragma mark - Equality - (NSUInteger)hash { - return [self.name hash]; + return [self.name hash]; } - (BOOL)isEqualToAttribute:(QKAttribute *)attribute { - return [self.name isEqualToString:attribute.name]; + return [self.name isEqualToString:attribute.name]; } - (BOOL)isEqual:(id)object { - return object == self || ([object isKindOfClass:[QKAttribute class]] && [self isEqualToAttribute:object]); + return object == self || ([object isKindOfClass:[QKAttribute class]] && [self isEqualToAttribute:object]); } #pragma mark - @@ -86,19 +86,19 @@ - (BOOL)isEqual:(id)object { // The following methods are implemented so that `[NSPredicate predicateWithFormat:@"%K", attribute]` will work - (NSString *)description { - return self.name; + return self.name; } - (NSRange)rangeOfString:(NSString *)aString { - return [self.name rangeOfString:aString]; + return [self.name rangeOfString:aString]; } - (NSArray *)componentsSeparatedByString:(NSString *)separator { - return [self.name componentsSeparatedByString:separator]; + return [self.name componentsSeparatedByString:separator]; } - (NSUInteger)length { - return [self.name length]; + return [self.name length]; } #pragma mark - Comparison @@ -108,13 +108,13 @@ - (NSPredicate *)predicateWithRightExpression:(NSExpression *)expression type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options { - NSExpression *leftExpression = [self expression]; + NSExpression *leftExpression = [self expression]; - return [NSComparisonPredicate predicateWithLeftExpression:leftExpression - rightExpression:expression - modifier:modifier - type:type - options:options]; + return [NSComparisonPredicate predicateWithLeftExpression:leftExpression + rightExpression:expression + modifier:modifier + type:type + options:options]; } @end @@ -122,182 +122,182 @@ - (NSPredicate *)predicateWithRightExpression:(NSExpression *)expression @implementation QKAttribute (Predicate) - (NSPredicate *)equal:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:options]; } - (NSPredicate *)equal:(id)value { - return [self equal:value options:0]; + return [self equal:value options:0]; } - (NSPredicate *)notEqual:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSNotEqualToPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSNotEqualToPredicateOperatorType + options:options]; } - (NSPredicate *)notEqual:(id)value { - return [self notEqual:value options:0]; + return [self notEqual:value options:0]; } - (NSPredicate *)beginsWith:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSBeginsWithPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSBeginsWithPredicateOperatorType + options:options]; } - (NSPredicate *)beginsWith:(id)value { - return [self beginsWith:value options:0]; + return [self beginsWith:value options:0]; } - (NSPredicate *)endsWith:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEndsWithPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSEndsWithPredicateOperatorType + options:options]; } - (NSPredicate *)endsWith:(id)value { - return [self endsWith:value options:0]; + return [self endsWith:value options:0]; } - (NSPredicate *)like:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLikePredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSLikePredicateOperatorType + options:options]; } - (NSPredicate *)like:(id)value { - return [self like:value options:0]; + return [self like:value options:0]; } - (NSPredicate *)matches:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSMatchesPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSMatchesPredicateOperatorType + options:options]; } - (NSPredicate *)matches:(id)value { - return [self matches:value options:0]; + return [self matches:value options:0]; } - (NSPredicate *)greaterThan:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSGreaterThanPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSGreaterThanPredicateOperatorType + options:0]; } - (NSPredicate *)greaterThanOrEqualTo:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSGreaterThanOrEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSGreaterThanOrEqualToPredicateOperatorType + options:0]; } - (NSPredicate *)lessThan:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLessThanPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSLessThanPredicateOperatorType + options:0]; } - (NSPredicate *)lessThanOrEqualTo:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLessThanOrEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSLessThanOrEqualToPredicateOperatorType + options:0]; } - (NSPredicate *)isNil { - NSExpression *expression = [NSExpression expressionForConstantValue:nil]; + NSExpression *expression = [NSExpression expressionForConstantValue:nil]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:0]; } - (NSPredicate *)between:(id)minimumValue and:(id)maxiumValue { - NSParameterAssert(minimumValue != nil); - NSParameterAssert(maxiumValue != nil); + NSParameterAssert(minimumValue != nil); + NSParameterAssert(maxiumValue != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:@[minimumValue, maxiumValue]]; + NSExpression *expression = [NSExpression expressionForConstantValue:@[minimumValue, maxiumValue]]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSBetweenPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSBetweenPredicateOperatorType + options:0]; } - (NSPredicate *)in:(id)set { - NSParameterAssert(set != nil); + NSParameterAssert(set != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:set]; + NSExpression *expression = [NSExpression expressionForConstantValue:set]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSInPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSInPredicateOperatorType + options:0]; } - (NSPredicate *)contains:(id)value options:(NSComparisonPredicateOptions)options { - NSParameterAssert(value != nil); + NSParameterAssert(value != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:value]; + NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSContainsPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSContainsPredicateOperatorType + options:options]; } - (NSPredicate *)contains:(id)value { - return [self contains:value options:0]; + return [self contains:value options:0]; } - (NSPredicate *)isYes { - NSExpression *expression = [NSExpression expressionForConstantValue:@YES]; + NSExpression *expression = [NSExpression expressionForConstantValue:@YES]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:0]; } - (NSPredicate *)isNo { - NSExpression *expression = [NSExpression expressionForConstantValue:@NO]; + NSExpression *expression = [NSExpression expressionForConstantValue:@NO]; - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression + modifier:NSDirectPredicateModifier + type:NSEqualToPredicateOperatorType + options:0]; } @end @@ -305,11 +305,11 @@ - (NSPredicate *)isNo { @implementation QKAttribute (Sorting) - (NSSortDescriptor *)ascending { - return [[NSSortDescriptor alloc] initWithKey:self.name ascending:YES]; + return [[NSSortDescriptor alloc] initWithKey:self.name ascending:YES]; } - (NSSortDescriptor *)descending { - return [[NSSortDescriptor alloc] initWithKey:self.name ascending:NO]; + return [[NSSortDescriptor alloc] initWithKey:self.name ascending:NO]; } @end diff --git a/QueryKit/ObjectiveC/QKAttribute.swift b/QueryKit/ObjectiveC/QKAttribute.swift index 148c615..d3bc9e2 100644 --- a/QueryKit/ObjectiveC/QKAttribute.swift +++ b/QueryKit/ObjectiveC/QKAttribute.swift @@ -1,13 +1,13 @@ import Foundation extension Attribute { - public func asQKAttribute() -> QKAttribute { - return QKAttribute(name: name) - } + public func asQKAttribute() -> QKAttribute { + return QKAttribute(name: name) + } } extension QKAttribute { - public func asAttribute() -> Attribute { - return Attribute(name) - } + public func asAttribute() -> Attribute { + return Attribute(name) + } } diff --git a/QueryKit/ObjectiveC/QKQuerySet.h b/QueryKit/ObjectiveC/QKQuerySet.h index f0c39b9..ff37b3c 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.h +++ b/QueryKit/ObjectiveC/QKQuerySet.h @@ -147,9 +147,9 @@ @end - @interface NSManagedObject (QKQuerySet) +/// Returns a queryset for this object in the given context. + (QKQuerySet *)querySetWithManagedObjectContext:(NSManagedObjectContext *)context; @end diff --git a/QueryKit/ObjectiveC/QKQuerySet.m b/QueryKit/ObjectiveC/QKQuerySet.m index 252db94..329f19b 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.m +++ b/QueryKit/ObjectiveC/QKQuerySet.m @@ -21,181 +21,181 @@ @implementation QKQuerySet #pragma mark - Creation - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription { - return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:nil sortDescriptors:nil range:NSMakeRange(NSNotFound, NSNotFound)]; + return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:nil sortDescriptors:nil range:NSMakeRange(NSNotFound, NSNotFound)]; } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest { - NSParameterAssert(fetchRequest != nil); + NSParameterAssert(fetchRequest != nil); - NSEntityDescription *entityDescription = [fetchRequest entity]; - NSPredicate *predicate = [fetchRequest predicate]; - NSArray *sortDescriptors = [fetchRequest sortDescriptors]; + NSEntityDescription *entityDescription = [fetchRequest entity]; + NSPredicate *predicate = [fetchRequest predicate]; + NSArray *sortDescriptors = [fetchRequest sortDescriptors]; - return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)]; + return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)]; } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription predicate:(NSPredicate *)predicate sortDescriptors:(NSArray *)sortDescriptors range:(NSRange)range { - NSParameterAssert(managedObjectContext != nil); - NSParameterAssert(entityDescription != nil); - - if (self = [super init]) { - _managedObjectContext = managedObjectContext; - _entityDescription = entityDescription; - _predicate = [predicate copy]; - _sortDescriptors = sortDescriptors? [sortDescriptors copy] : @[]; - _range = range; - } - - return self; + NSParameterAssert(managedObjectContext != nil); + NSParameterAssert(entityDescription != nil); + + if (self = [super init]) { + _managedObjectContext = managedObjectContext; + _entityDescription = entityDescription; + _predicate = [predicate copy]; + _sortDescriptors = sortDescriptors? [sortDescriptors copy] : @[]; + _range = range; + } + + return self; } - (instancetype)init { - NSString *reason = [NSString stringWithFormat:@"%@ Failed to call designated initializer.", NSStringFromClass([self class])]; - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil]; + NSString *reason = [NSString stringWithFormat:@"%@ Failed to call designated initializer.", NSStringFromClass([self class])]; + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil]; } #pragma mark - Equality - (NSUInteger)hash { - return [self.managedObjectContext hash]; + return [self.managedObjectContext hash]; } - (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } + if (self == object) { + return YES; + } - if ([object isKindOfClass:[QKQuerySet class]] == NO) { - return NO; - } + if ([object isKindOfClass:[QKQuerySet class]] == NO) { + return NO; + } - return [self isEqualToQuerySet:object]; + return [self isEqualToQuerySet:object]; } - (BOOL)isEqualToQuerySet:(QKQuerySet *)queryset { - return ( - [self.managedObjectContext isEqual:[queryset managedObjectContext]] && - [self.entityDescription isEqual:[queryset entityDescription]] && - [self.predicate isEqual:[queryset predicate]] && - [self.sortDescriptors isEqual:[queryset sortDescriptors]] && - NSEqualRanges(self.range, queryset.range) - ); + return ( + [self.managedObjectContext isEqual:[queryset managedObjectContext]] && + [self.entityDescription isEqual:[queryset entityDescription]] && + [self.predicate isEqual:[queryset predicate]] && + [self.sortDescriptors isEqual:[queryset sortDescriptors]] && + NSEqualRanges(self.range, queryset.range) + ); } #pragma mark - NSCopying - (instancetype)copyWithZone:(NSZone *)zone { - return [[[self class] allocWithZone:zone] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:self.predicate sortDescriptors:self.sortDescriptors range:self.range]; + return [[[self class] allocWithZone:zone] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:self.predicate sortDescriptors:self.sortDescriptors range:self.range]; } #pragma mark - NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { - if (_resultsCache == nil) { - [self array:nil]; - } + if (_resultsCache == nil) { + [self array:nil]; + } - return [_resultsCache countByEnumeratingWithState:state objects:buffer count:len]; + return [_resultsCache countByEnumeratingWithState:state objects:buffer count:len]; } #pragma mark - Fetching - (NSFetchRequest *)fetchRequest { - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:_entityDescription]; - [fetchRequest setPredicate:self.predicate]; - [fetchRequest setSortDescriptors:self.sortDescriptors]; - - if (self.range.location != NSNotFound) { - fetchRequest.fetchOffset = self.range.location; - fetchRequest.fetchLimit = self.range.length; - } + NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; + [fetchRequest setEntity:_entityDescription]; + [fetchRequest setPredicate:self.predicate]; + [fetchRequest setSortDescriptors:self.sortDescriptors]; - return fetchRequest; + if (self.range.location != NSNotFound) { + fetchRequest.fetchOffset = self.range.location; + fetchRequest.fetchLimit = self.range.length; + } + + return fetchRequest; } - (NSUInteger)count:(NSError **)error { - NSUInteger count = 0; + NSUInteger count = 0; - if (_resultsCache) { - count = [_resultsCache count]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - count = [self.managedObjectContext countForFetchRequest:fetchRequest error:error]; - } + if (_resultsCache) { + count = [_resultsCache count]; + } else { + NSFetchRequest *fetchRequest = [self fetchRequest]; + count = [self.managedObjectContext countForFetchRequest:fetchRequest error:error]; + } - return count; + return count; } - (NSArray *)array:(NSError **)error { - if (_resultsCache == nil) { - _resultsCache = [self.managedObjectContext executeFetchRequest:[self fetchRequest] error:error]; - } + if (_resultsCache == nil) { + _resultsCache = [self.managedObjectContext executeFetchRequest:[self fetchRequest] error:error]; + } - return _resultsCache; + return _resultsCache; } - (NSSet *)set:(NSError **)error { - NSArray *array = [self array:error]; - NSSet *set; + NSArray *array = [self array:error]; + NSSet *set; - if (array != nil) { - set = [NSSet setWithArray:array]; - } + if (array != nil) { + set = [NSSet setWithArray:array]; + } - return set; + return set; } - (NSOrderedSet *)orderedSet:(NSError **)error { - NSArray *array = [self array:error]; - NSOrderedSet *orderedSet; + NSArray *array = [self array:error]; + NSOrderedSet *orderedSet; - if (array != nil) { - orderedSet = [NSOrderedSet orderedSetWithArray:array]; - } + if (array != nil) { + orderedSet = [NSOrderedSet orderedSetWithArray:array]; + } - return orderedSet; + return orderedSet; } - (BOOL)enumerateObjects:(void (^)(NSManagedObject *object, NSUInteger index, BOOL *stop))block error:(NSError **)error { - NSArray *array = [self array:error]; + NSArray *array = [self array:error]; - if (array != nil) { - [array enumerateObjectsUsingBlock:block]; - } + if (array != nil) { + [array enumerateObjectsUsingBlock:block]; + } - return array != nil; + return array != nil; } - (BOOL)each:(void (^)(NSManagedObject *managedObject))block error:(NSError **)error { - NSArray *array = [self array:error]; + NSArray *array = [self array:error]; - if (array != nil) { - for (NSManagedObject *managedObject in array) { - block(managedObject); - } + if (array != nil) { + for (NSManagedObject *managedObject in array) { + block(managedObject); } + } - return array != nil; + return array != nil; } #pragma mark - Deletion - (NSUInteger)deleteObjects:(NSError **)error { - NSArray *array = [self array:error]; + NSArray *array = [self array:error]; - NSUInteger count = 0; + NSUInteger count = 0; - if (array != nil) { - NSManagedObjectContext *managedObjectContext = self.managedObjectContext; + if (array != nil) { + NSManagedObjectContext *managedObjectContext = self.managedObjectContext; - for (NSManagedObject *managedObject in array) { - [managedObjectContext deleteObject:managedObject]; - ++count; - } + for (NSManagedObject *managedObject in array) { + [managedObjectContext deleteObject:managedObject]; + ++count; } + } - return count; + return count; } @end @@ -203,17 +203,17 @@ - (NSUInteger)deleteObjects:(NSError **)error { @implementation QKQuerySet (Sorting) - (instancetype)orderBy:(NSArray *)sortDescriptors { - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; + return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; } - (instancetype)reverse { - NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithCapacity:[_sortDescriptors count]]; + NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithCapacity:[_sortDescriptors count]]; - for (NSSortDescriptor *sortDescriptor in _sortDescriptors) { - [sortDescriptors addObject:[sortDescriptor reversedSortDescriptor]]; - } + for (NSSortDescriptor *sortDescriptor in _sortDescriptors) { + [sortDescriptors addObject:[sortDescriptor reversedSortDescriptor]]; + } - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; + return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; } @end @@ -221,21 +221,21 @@ - (instancetype)reverse { @implementation QKQuerySet (Filtering) - (instancetype)exclude:(NSPredicate *)predicate { - predicate = [[NSCompoundPredicate alloc] initWithType:NSNotPredicateType subpredicates:@[predicate]]; + predicate = [[NSCompoundPredicate alloc] initWithType:NSNotPredicateType subpredicates:@[predicate]]; - if (_predicate) { - predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; - } + if (_predicate) { + predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; + } - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; + return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; } - (instancetype)filter:(NSPredicate *)predicate { - if (_predicate) { - predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; - } + if (_predicate) { + predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; + } - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; + return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; } @end @@ -243,59 +243,59 @@ - (instancetype)filter:(NSPredicate *)predicate { @implementation QKQuerySet (SingleObject) - (NSManagedObject *)object:(NSError **)error { - NSManagedObject *managedObject; - NSArray *array; + NSManagedObject *managedObject; + NSArray *array; - if (_resultsCache) { - array = _resultsCache; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - fetchRequest.fetchBatchSize = 1; // Only request one + if (_resultsCache) { + array = _resultsCache; + } else { + NSFetchRequest *fetchRequest = [self fetchRequest]; + fetchRequest.fetchBatchSize = 1; // Only request one - array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - } + array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; + } - NSUInteger count = [array count]; + NSUInteger count = [array count]; - if (count == 1) { - managedObject = [array firstObject]; - } else if ((count > 1) && error != nil) { - *error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{ - NSLocalizedDescriptionKey: @"Find object in fetch request failed, should only result in a single result.", - }]; - } + if (count == 1) { + managedObject = [array firstObject]; + } else if ((count > 1) && error != nil) { + *error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{ + NSLocalizedDescriptionKey: @"Find object in fetch request failed, should only result in a single result.", + }]; + } - return managedObject; + return managedObject; } - (NSManagedObject *)firstObject:(NSError **)error { - NSManagedObject *managedObject; + NSManagedObject *managedObject; - if (_resultsCache) { - managedObject = [_resultsCache firstObject]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - [fetchRequest setFetchLimit:1]; + if (_resultsCache) { + managedObject = [_resultsCache firstObject]; + } else { + NSFetchRequest *fetchRequest = [self fetchRequest]; + [fetchRequest setFetchLimit:1]; - NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - managedObject = [array firstObject]; - } + NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; + managedObject = [array firstObject]; + } - return managedObject; + return managedObject; } - (NSManagedObject *)lastObject:(NSError **)error { - NSManagedObject *managedObject; - - if (_resultsCache) { - managedObject = [_resultsCache lastObject]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - managedObject = [array lastObject]; - } - - return managedObject; + NSManagedObject *managedObject; + + if (_resultsCache) { + managedObject = [_resultsCache lastObject]; + } else { + NSFetchRequest *fetchRequest = [self fetchRequest]; + NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; + managedObject = [array lastObject]; + } + + return managedObject; } @end @@ -303,12 +303,12 @@ - (NSManagedObject *)lastObject:(NSError **)error { @implementation NSManagedObject (QKQuerySet) + (NSString *)entityName { - return NSStringFromClass([self class]); + return NSStringFromClass([self class]); } + (QKQuerySet *)querySetWithManagedObjectContext:(NSManagedObjectContext *)context { - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:context]; - return [[QKQuerySet alloc] initWithManagedObjectContext:context entityDescription:entityDescription]; + NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:context]; + return [[QKQuerySet alloc] initWithManagedObjectContext:context entityDescription:entityDescription]; } @end diff --git a/QueryKit/ObjectiveC/QKQuerySet.swift b/QueryKit/ObjectiveC/QKQuerySet.swift index 30c52e9..439a4f8 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.swift +++ b/QueryKit/ObjectiveC/QKQuerySet.swift @@ -1,28 +1,28 @@ import Foundation extension QuerySet { - public func asQKQuerySet() -> QKQuerySet { - let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context) + public func asQKQuerySet() -> QKQuerySet { + let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context) - var nsrange:NSRange = NSMakeRange(NSNotFound, NSNotFound) - if let range = self.range { - nsrange = NSMakeRange(range.startIndex, range.endIndex - range.startIndex) - } - - return QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:nsrange) + var nsrange:NSRange = NSMakeRange(NSNotFound, NSNotFound) + if let range = self.range { + nsrange = NSMakeRange(range.startIndex, range.endIndex - range.startIndex) } + + return QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:nsrange) + } } extension QKQuerySet { - public func asQuerySet() -> QuerySet { - let queryset = QuerySet(managedObjectContext, entityDescription.name!) - .orderBy(sortDescriptors as [NSSortDescriptor]) - .filter(predicate) + public func asQuerySet() -> QuerySet { + let queryset = QuerySet(managedObjectContext, entityDescription.name!) + .orderBy(sortDescriptors as [NSSortDescriptor]) + .filter(predicate) - if range.location != NSNotFound { - return queryset[range.location..<(range.location + range.length)] - } - - return queryset + if range.location != NSNotFound { + return queryset[range.location..<(range.location + range.length)] } + + return queryset + } } diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index b3ad728..75b2fe7 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -9,13 +9,13 @@ import Foundation public func && (left: NSPredicate, right: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [left, right]) + return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [left, right]) } public func || (left: NSPredicate, right: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [left, right]) + return NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [left, right]) } prefix public func ! (left: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [left]) + return NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [left]) } diff --git a/QueryKit/QueryKit.swift b/QueryKit/QueryKit.swift deleted file mode 100644 index ba12018..0000000 --- a/QueryKit/QueryKit.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// QueryKit.swift -// QueryKit -// -// Created by Kyle Fuller on 19/06/2014. -// -// - diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 9ebd122..172cc0d 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -10,246 +10,246 @@ import Foundation import CoreData #if os(OSX) && COCOAPODS -import AppKit + import AppKit #endif /// Represents a lazy database lookup for a set of objects. public class QuerySet : SequenceType, Equatable { - /// Returns the managed object context that will be used to execute any requests. - public let context:NSManagedObjectContext + /// Returns the managed object context that will be used to execute any requests. + public let context:NSManagedObjectContext - /// Returns the name of the entity the request is configured to fetch. - public let entityName:String + /// Returns the name of the entity the request is configured to fetch. + public let entityName:String - /// Returns the sort descriptors of the receiver. - public let sortDescriptors = [NSSortDescriptor]() + /// Returns the sort descriptors of the receiver. + public let sortDescriptors = [NSSortDescriptor]() - /// Returns the predicate of the receiver. - public let predicate:NSPredicate? + /// Returns the predicate of the receiver. + public let predicate:NSPredicate? - public let range:Range? + public let range:Range? - // MARK: Initialization + // MARK: Initialization - public init(_ context:NSManagedObjectContext, _ entityName:String) { - self.context = context - self.entityName = entityName - } - - public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { - self.context = queryset.context - self.entityName = queryset.entityName + public init(_ context:NSManagedObjectContext, _ entityName:String) { + self.context = context + self.entityName = entityName + } - if let sortDescriptors = sortDescriptors { - self.sortDescriptors = sortDescriptors - } + public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { + self.context = queryset.context + self.entityName = queryset.entityName - self.predicate = predicate - self.range = range + if let sortDescriptors = sortDescriptors { + self.sortDescriptors = sortDescriptors } - // MARK: Sorting + self.predicate = predicate + self.range = range + } - /// Returns a new QuerySet containing objects ordered by the given sort descriptor. - public func orderBy(sortDescriptor:NSSortDescriptor) -> QuerySet { - return orderBy([sortDescriptor]) - } + // MARK: Sorting - /// Returns a new QuerySet containing objects ordered by the given sort descriptors. - public func orderBy(sortDescriptors:[NSSortDescriptor]) -> QuerySet { - return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:range) - } + /// Returns a new QuerySet containing objects ordered by the given sort descriptor. + public func orderBy(sortDescriptor:NSSortDescriptor) -> QuerySet { + return orderBy([sortDescriptor]) + } + + /// Returns a new QuerySet containing objects ordered by the given sort descriptors. + public func orderBy(sortDescriptors:[NSSortDescriptor]) -> QuerySet { + return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:range) + } - /// Reverses the ordering of the QuerySet - public func reverse() -> QuerySet { - func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { - #if os(OSX) && COCOAPODS - return NSSortDescriptor(key: sortDescriptor.key()!, ascending: !sortDescriptor.ascending) - #else - return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) - #endif - } - - return QuerySet(queryset:self, sortDescriptors:map(sortDescriptors, reverseSortDescriptor), predicate:predicate, range:range) + /// Reverses the ordering of the QuerySet + public func reverse() -> QuerySet { + func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { + #if os(OSX) && COCOAPODS + return NSSortDescriptor(key: sortDescriptor.key()!, ascending: !sortDescriptor.ascending) + #else + return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) + #endif } - // MARK: Filtering + return QuerySet(queryset:self, sortDescriptors:map(sortDescriptors, reverseSortDescriptor), predicate:predicate, range:range) + } - /// Returns a new QuerySet containing objects that match the given predicate. - public func filter(predicate:NSPredicate) -> QuerySet { - var futurePredicate = predicate + // MARK: Filtering - if let existingPredicate = self.predicate { - futurePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [existingPredicate, predicate]) - } + /// Returns a new QuerySet containing objects that match the given predicate. + public func filter(predicate:NSPredicate) -> QuerySet { + var futurePredicate = predicate - return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:futurePredicate, range:range) + if let existingPredicate = self.predicate { + futurePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [existingPredicate, predicate]) } - /// Returns a new QuerySet containing objects that match the given predicates. - public func filter(predicates:[NSPredicate]) -> QuerySet { - let newPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) - return filter(newPredicate) - } + return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:futurePredicate, range:range) + } - /// Returns a new QuerySet containing objects that exclude the given predicate. - public func exclude(predicate:NSPredicate) -> QuerySet { - let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [predicate]) - return filter(excludePredicate) - } + /// Returns a new QuerySet containing objects that match the given predicates. + public func filter(predicates:[NSPredicate]) -> QuerySet { + let newPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) + return filter(newPredicate) + } - /// Returns a new QuerySet containing objects that exclude the given predicates. - public func exclude(predicates:[NSPredicate]) -> QuerySet { - let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) - return exclude(excludePredicate) - } + /// Returns a new QuerySet containing objects that exclude the given predicate. + public func exclude(predicate:NSPredicate) -> QuerySet { + let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [predicate]) + return filter(excludePredicate) + } - // MARK: Subscripting - - public subscript(index: Int) -> (object:T?, error:NSError?) { - get { - var request = fetchRequest - request.fetchOffset = index - request.fetchLimit = 1 - - var error:NSError? - if let items = context.executeFetchRequest(request, error:&error) { - return (object:items.first as T?, error:error) - } else { - return (object: nil, error: error) - } - } - } + /// Returns a new QuerySet containing objects that exclude the given predicates. + public func exclude(predicates:[NSPredicate]) -> QuerySet { + let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) + return exclude(excludePredicate) + } - /// Returns the object at the specified index. - public subscript(index: Int) -> T? { - get { - return self[index].object - } - } + // MARK: Subscripting - public subscript(range:Range) -> QuerySet { - get { - var fullRange = range + public subscript(index: Int) -> (object:T?, error:NSError?) { + get { + var request = fetchRequest + request.fetchOffset = index + request.fetchLimit = 1 - if let currentRange = self.range { - fullRange = Range(start: currentRange.startIndex + range.startIndex, end: range.endIndex) - } + var error:NSError? + if let items = context.executeFetchRequest(request, error:&error) { + return (object:items.first as T?, error:error) + } else { + return (object: nil, error: error) + } + } + } - return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:fullRange) - } + /// Returns the object at the specified index. + public subscript(index: Int) -> T? { + get { + return self[index].object } + } - // Mark: Getters + public subscript(range:Range) -> QuerySet { + get { + var fullRange = range - public var first: T? { - get { - return self[0].object + if let currentRange = self.range { + fullRange = Range(start: currentRange.startIndex + range.startIndex, end: range.endIndex) } + + return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:fullRange) } + } + + // Mark: Getters - public var last: T? { - get { - return reverse().first - } + public var first: T? { + get { + return self[0].object } + } - // MARK: Conversion + public var last: T? { + get { + return reverse().first + } + } - public var fetchRequest:NSFetchRequest { - var request = NSFetchRequest(entityName:entityName) - request.predicate = predicate - request.sortDescriptors = sortDescriptors + // MARK: Conversion - if let range = range { - request.fetchOffset = range.startIndex - request.fetchLimit = range.endIndex - range.startIndex - } + public var fetchRequest:NSFetchRequest { + var request = NSFetchRequest(entityName:entityName) + request.predicate = predicate + request.sortDescriptors = sortDescriptors - return request + if let range = range { + request.fetchOffset = range.startIndex + request.fetchLimit = range.endIndex - range.startIndex } - public func array() -> (objects:([T]?), error:NSError?) { - var error:NSError? - var objects = context.executeFetchRequest(fetchRequest, error:&error) as? [T] - return (objects:objects, error:error) - } + return request + } - public func array() -> [T]? { - return array().objects - } + public func array() -> (objects:([T]?), error:NSError?) { + var error:NSError? + var objects = context.executeFetchRequest(fetchRequest, error:&error) as? [T] + return (objects:objects, error:error) + } - // MARK: Count + public func array() -> [T]? { + return array().objects + } - public func count() -> (count:Int?, error:NSError?) { - var error:NSError? - var count:Int? = context.countForFetchRequest(fetchRequest, error: &error) + // MARK: Count - if count! == NSNotFound { - count = nil - } + public func count() -> (count:Int?, error:NSError?) { + var error:NSError? + var count:Int? = context.countForFetchRequest(fetchRequest, error: &error) - return (count:count, error:error) + if count! == NSNotFound { + count = nil } - /// Returns the count of objects matching the QuerySet. - public func count() -> Int? { - return count().count - } + return (count:count, error:error) + } - // MARK: Exists + /// Returns the count of objects matching the QuerySet. + public func count() -> Int? { + return count().count + } - /** Returns true if the QuerySet contains any results, and false if not. - :note: Returns nil if the operation could not be completed. - */ - public func exists() -> Bool? { - let result:Int? = count() + // MARK: Exists - if let result = result { - return result > 0 - } + /** Returns true if the QuerySet contains any results, and false if not. + :note: Returns nil if the operation could not be completed. + */ + public func exists() -> Bool? { + let result:Int? = count() - return nil + if let result = result { + return result > 0 } - // MARK: Deletion + return nil + } - /// Deletes all the objects matching the QuerySet. - public func delete() -> (count:Int, error:NSError?) { - var result = array() as (objects:([T]?), error:NSError?) - var deletedCount = 0 + // MARK: Deletion - if let objects = result.objects { - for object in objects { - context.deleteObject(object) - } + /// Deletes all the objects matching the QuerySet. + public func delete() -> (count:Int, error:NSError?) { + var result = array() as (objects:([T]?), error:NSError?) + var deletedCount = 0 - deletedCount = objects.count - } + if let objects = result.objects { + for object in objects { + context.deleteObject(object) + } - return (count:deletedCount, error:result.error) + deletedCount = objects.count } - // MARK: Sequence + return (count:deletedCount, error:result.error) + } + + // MARK: Sequence - public func generate() -> IndexingGenerator> { - var result = self.array() as (objects:([T]?), error:NSError?) - - if let objects = result.objects { - return objects.generate() - } - - return [].generate() + public func generate() -> IndexingGenerator> { + var result = self.array() as (objects:([T]?), error:NSError?) + + if let objects = result.objects { + return objects.generate() } + + return [].generate() + } } public func == (lhs: QuerySet, rhs: QuerySet) -> Bool { - let context = lhs.context == rhs.context - let entityName = lhs.entityName == rhs.entityName - let sortDescriptors = lhs.sortDescriptors == rhs.sortDescriptors - let predicate = lhs.predicate == rhs.predicate - let startIndex = lhs.range?.startIndex == rhs.range?.startIndex - let endIndex = lhs.range?.endIndex == rhs.range?.endIndex - return context && entityName && sortDescriptors && predicate && startIndex && endIndex + let context = lhs.context == rhs.context + let entityName = lhs.entityName == rhs.entityName + let sortDescriptors = lhs.sortDescriptors == rhs.sortDescriptors + let predicate = lhs.predicate == rhs.predicate + let startIndex = lhs.range?.startIndex == rhs.range?.startIndex + let endIndex = lhs.range?.endIndex == rhs.range?.endIndex + return context && entityName && sortDescriptors && predicate && startIndex && endIndex } diff --git a/QueryKitTests/AttributeTests.swift b/QueryKitTests/AttributeTests.swift index 1288d44..4474128 100644 --- a/QueryKitTests/AttributeTests.swift +++ b/QueryKitTests/AttributeTests.swift @@ -10,126 +10,126 @@ import XCTest import QueryKit class AttributeTests: XCTestCase { - var attribute:Attribute! - - override func setUp() { - super.setUp() - - attribute = Attribute("age") - } - - func testAttributeHasName() { - XCTAssertEqual(attribute.name, "age") - } - - func testAttributeExpression() { - XCTAssertEqual(attribute.expression.keyPath, "age") - } - - func testEqualAttributesAreEquatable() { - XCTAssertEqual(attribute, Attribute("age")) - } - - func testCompoundAttributeCreation() { - let personCompanyNameAttribute = Attribute(attributes:["company", "name"]) - - XCTAssertEqual(personCompanyNameAttribute.name, "company.name") - XCTAssertEqual(personCompanyNameAttribute.expression.keyPath, "company.name") - } - - // Sorting - - func testAscendingSortDescriptor() { - XCTAssertEqual(attribute.ascending(), NSSortDescriptor(key: "age", ascending: true)) - } - - func testDescendingSortDescriptor() { - XCTAssertEqual(attribute.descending(), NSSortDescriptor(key: "age", ascending: false)) - } - - // Operators - - func testEqualityOperator() { - var predicate:NSPredicate = (attribute == 10) - XCTAssertEqual(predicate, NSPredicate(format:"age == 10")!) - } - - func testInequalityOperator() { - var predicate:NSPredicate = (attribute != 10) - XCTAssertEqual(predicate, NSPredicate(format:"age != 10")!) - } - - func testGreaterThanOperator() { - var predicate:NSPredicate = (attribute > 10) - XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) - } - - func testGreaterOrEqualThanOperator() { - var predicate:NSPredicate = (attribute >= 10) - XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")!) - } - - func testLessThanOperator() { - var predicate:NSPredicate = (attribute < 10) - XCTAssertEqual(predicate, NSPredicate(format:"age < 10")!) - } - - func testLessOrEqualThanOperator() { - var predicate:NSPredicate = (attribute <= 10) - XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")!) - } - - func testLikeOperator() { - var predicate:NSPredicate = (attribute ~= 10) - XCTAssertEqual(predicate, NSPredicate(format:"age LIKE 10")!) - } - - func testInOperator() { - var predicate:NSPredicate = (attribute << [5, 10]) - XCTAssertEqual(predicate, NSPredicate(format:"age IN %@", [5, 10])!) - } - - func testBetweenRangeOperator() { - var predicate:NSPredicate = attribute << (5..<10) - XCTAssertEqual(predicate, NSPredicate(format:"age BETWEEN %@", [5, 10])!) - } - - func testOptionalEqualityOperator() { - let attribute = Attribute("name") - var predicate:NSPredicate = (attribute == "kyle") - XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")!) - } - - func testOptionalNSObjectEqualityOperator() { - let attribute = Attribute("name") - var predicate:NSPredicate = (attribute == "kyle") - XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")!) - } + var attribute:Attribute! + + override func setUp() { + super.setUp() + + attribute = Attribute("age") + } + + func testAttributeHasName() { + XCTAssertEqual(attribute.name, "age") + } + + func testAttributeExpression() { + XCTAssertEqual(attribute.expression.keyPath, "age") + } + + func testEqualAttributesAreEquatable() { + XCTAssertEqual(attribute, Attribute("age")) + } + + func testCompoundAttributeCreation() { + let personCompanyNameAttribute = Attribute(attributes:["company", "name"]) + + XCTAssertEqual(personCompanyNameAttribute.name, "company.name") + XCTAssertEqual(personCompanyNameAttribute.expression.keyPath, "company.name") + } + + // Sorting + + func testAscendingSortDescriptor() { + XCTAssertEqual(attribute.ascending(), NSSortDescriptor(key: "age", ascending: true)) + } + + func testDescendingSortDescriptor() { + XCTAssertEqual(attribute.descending(), NSSortDescriptor(key: "age", ascending: false)) + } + + // Operators + + func testEqualityOperator() { + var predicate:NSPredicate = (attribute == 10) + XCTAssertEqual(predicate, NSPredicate(format:"age == 10")!) + } + + func testInequalityOperator() { + var predicate:NSPredicate = (attribute != 10) + XCTAssertEqual(predicate, NSPredicate(format:"age != 10")!) + } + + func testGreaterThanOperator() { + var predicate:NSPredicate = (attribute > 10) + XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) + } + + func testGreaterOrEqualThanOperator() { + var predicate:NSPredicate = (attribute >= 10) + XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")!) + } + + func testLessThanOperator() { + var predicate:NSPredicate = (attribute < 10) + XCTAssertEqual(predicate, NSPredicate(format:"age < 10")!) + } + + func testLessOrEqualThanOperator() { + var predicate:NSPredicate = (attribute <= 10) + XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")!) + } + + func testLikeOperator() { + var predicate:NSPredicate = (attribute ~= 10) + XCTAssertEqual(predicate, NSPredicate(format:"age LIKE 10")!) + } + + func testInOperator() { + var predicate:NSPredicate = (attribute << [5, 10]) + XCTAssertEqual(predicate, NSPredicate(format:"age IN %@", [5, 10])!) + } + + func testBetweenRangeOperator() { + var predicate:NSPredicate = attribute << (5..<10) + XCTAssertEqual(predicate, NSPredicate(format:"age BETWEEN %@", [5, 10])!) + } + + func testOptionalEqualityOperator() { + let attribute = Attribute("name") + var predicate:NSPredicate = (attribute == "kyle") + XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")!) + } + + func testOptionalNSObjectEqualityOperator() { + let attribute = Attribute("name") + var predicate:NSPredicate = (attribute == "kyle") + XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")!) + } } class CollectionAttributeTests: XCTestCase { - func testCountOfSet() { - let setAttribute = Attribute("names") - let countAttribute = count(setAttribute) - XCTAssertEqual(countAttribute, Attribute("names.@count")) - } - - func testCountOfOrderedSet() { - let setAttribute = Attribute("names") - let countAttribute = count(setAttribute) - XCTAssertEqual(countAttribute, Attribute("names.@count")) - } + func testCountOfSet() { + let setAttribute = Attribute("names") + let countAttribute = count(setAttribute) + XCTAssertEqual(countAttribute, Attribute("names.@count")) + } + + func testCountOfOrderedSet() { + let setAttribute = Attribute("names") + let countAttribute = count(setAttribute) + XCTAssertEqual(countAttribute, Attribute("names.@count")) + } } class BoolAttributeTests: XCTestCase { - var attribute:Attribute! + var attribute:Attribute! - override func setUp() { - super.setUp() - attribute = Attribute("hasName") - } + override func setUp() { + super.setUp() + attribute = Attribute("hasName") + } - func testNotAttributeReturnsPredicate() { - XCTAssertEqual(!attribute, NSPredicate(format:"hasName == NO")!) - } + func testNotAttributeReturnsPredicate() { + XCTAssertEqual(!attribute, NSPredicate(format:"hasName == NO")!) + } } diff --git a/QueryKitTests/ExpressionTests.swift b/QueryKitTests/ExpressionTests.swift index 35a9398..1326a6c 100644 --- a/QueryKitTests/ExpressionTests.swift +++ b/QueryKitTests/ExpressionTests.swift @@ -10,46 +10,46 @@ import XCTest import QueryKit class ExpressionTests: XCTestCase { - var leftHandSide:NSExpression! - var rightHandSide:NSExpression! + var leftHandSide:NSExpression! + var rightHandSide:NSExpression! - override func setUp() { - super.setUp() + override func setUp() { + super.setUp() - leftHandSide = NSExpression(forKeyPath: "age") - rightHandSide = NSExpression(forConstantValue: 10) - } + leftHandSide = NSExpression(forKeyPath: "age") + rightHandSide = NSExpression(forConstantValue: 10) + } - func testEqualityOperator() { - XCTAssertEqual(leftHandSide == rightHandSide, NSPredicate(format:"age == 10")!) - } + func testEqualityOperator() { + XCTAssertEqual(leftHandSide == rightHandSide, NSPredicate(format:"age == 10")!) + } - func testInequalityOperator() { - XCTAssertEqual(leftHandSide != rightHandSide, NSPredicate(format:"age != 10")!) - } + func testInequalityOperator() { + XCTAssertEqual(leftHandSide != rightHandSide, NSPredicate(format:"age != 10")!) + } - func testGreaterThanOperator() { - let predicate:NSPredicate = leftHandSide > rightHandSide - XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) - } + func testGreaterThanOperator() { + let predicate:NSPredicate = leftHandSide > rightHandSide + XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) + } - func testGreaterOrEqualThanOperator() { - XCTAssertEqual(leftHandSide >= rightHandSide, NSPredicate(format:"age >= 10")!) - } + func testGreaterOrEqualThanOperator() { + XCTAssertEqual(leftHandSide >= rightHandSide, NSPredicate(format:"age >= 10")!) + } - func testLessThanOperator() { - XCTAssertEqual(leftHandSide < rightHandSide, NSPredicate(format:"age < 10")!) - } + func testLessThanOperator() { + XCTAssertEqual(leftHandSide < rightHandSide, NSPredicate(format:"age < 10")!) + } - func testLessOrEqualThanOperator() { - XCTAssertEqual(leftHandSide <= rightHandSide, NSPredicate(format:"age <= 10")!) - } + func testLessOrEqualThanOperator() { + XCTAssertEqual(leftHandSide <= rightHandSide, NSPredicate(format:"age <= 10")!) + } - func testLikeOperator() { - XCTAssertEqual(leftHandSide ~= rightHandSide, NSPredicate(format:"age LIKE 10")!) - } + func testLikeOperator() { + XCTAssertEqual(leftHandSide ~= rightHandSide, NSPredicate(format:"age LIKE 10")!) + } - func testInOperator() { - XCTAssertEqual(leftHandSide << rightHandSide, NSPredicate(format:"age IN 10")!) - } + func testInOperator() { + XCTAssertEqual(leftHandSide << rightHandSide, NSPredicate(format:"age IN 10")!) + } } diff --git a/QueryKitTests/ObjectiveC/QKAttributeTests.swift b/QueryKitTests/ObjectiveC/QKAttributeTests.swift index ddc8675..6802880 100644 --- a/QueryKitTests/ObjectiveC/QKAttributeTests.swift +++ b/QueryKitTests/ObjectiveC/QKAttributeTests.swift @@ -10,77 +10,77 @@ import XCTest import QueryKit class QKAttributeTests: XCTestCase { - var attribute:QKAttribute! + var attribute:QKAttribute! - override func setUp() { - super.setUp() + override func setUp() { + super.setUp() - attribute = QKAttribute(name: "age") - } + attribute = QKAttribute(name: "age") + } - func testAttributeHasName() { - XCTAssertEqual(attribute.name, "age") - } + func testAttributeHasName() { + XCTAssertEqual(attribute.name, "age") + } - func testAttributeExpression() { - XCTAssertEqual(attribute.expression().keyPath, "age") - } + func testAttributeExpression() { + XCTAssertEqual(attribute.expression().keyPath, "age") + } - func testEqualAttributesAreEquatable() { - XCTAssertEqual(attribute, QKAttribute(name: "age")) - } + func testEqualAttributesAreEquatable() { + XCTAssertEqual(attribute, QKAttribute(name: "age")) + } - // MARK: Conversion + // MARK: Conversion - func testConvertingAttributeToQKAttribute() { - let qkAttribute = Attribute("age").asQKAttribute() - XCTAssertEqual(qkAttribute, attribute) - } + func testConvertingAttributeToQKAttribute() { + let qkAttribute = Attribute("age").asQKAttribute() + XCTAssertEqual(qkAttribute, attribute) + } - func testConvertingQKAttributeToAttribute() { - XCTAssertEqual(attribute.asAttribute(), Attribute("age")) - } + func testConvertingQKAttributeToAttribute() { + XCTAssertEqual(attribute.asAttribute(), Attribute("age")) + } - // MARK: Ordering + // MARK: Ordering - func testAscendingSortDescriptor() { - XCTAssertEqual(attribute.ascending(), NSSortDescriptor(key: "age", ascending: true)) - } + func testAscendingSortDescriptor() { + XCTAssertEqual(attribute.ascending(), NSSortDescriptor(key: "age", ascending: true)) + } - func testDescendingSortDescriptor() { - XCTAssertEqual(attribute.descending(), NSSortDescriptor(key: "age", ascending: false)) - } + func testDescendingSortDescriptor() { + XCTAssertEqual(attribute.descending(), NSSortDescriptor(key: "age", ascending: false)) + } - // MARK: Operators + // MARK: Operators - func testEqualityOperator() { - let predicate = attribute.equal(10) - XCTAssertEqual(predicate, NSPredicate(format:"age == 10")!) - } + func testEqualityOperator() { + let predicate = attribute.equal(10) + XCTAssertEqual(predicate, NSPredicate(format:"age == 10")!) + } - func testInequalityOperator() { - let predicate = attribute.notEqual(10) - XCTAssertEqual(predicate, NSPredicate(format:"age != 10")!) - } + func testInequalityOperator() { + let predicate = attribute.notEqual(10) + XCTAssertEqual(predicate, NSPredicate(format:"age != 10")!) + } - func testGreaterThanOperator() { - let predicate = attribute.greaterThan(10) - XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) - } + func testGreaterThanOperator() { + let predicate = attribute.greaterThan(10) + XCTAssertEqual(predicate, NSPredicate(format:"age > 10")!) + } - func testGreaterOrEqualThanOperator() { - let predicate = attribute.greaterThanOrEqualTo(10) - XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")!) - } + func testGreaterOrEqualThanOperator() { + let predicate = attribute.greaterThanOrEqualTo(10) + XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")!) + } - func testLessThanOperator() { - let predicate = attribute.lessThan(10) - XCTAssertEqual(predicate, NSPredicate(format:"age < 10")!) - } + func testLessThanOperator() { + let predicate = attribute.lessThan(10) + XCTAssertEqual(predicate, NSPredicate(format:"age < 10")!) + } - func testLessOrEqualThanOperator() { - let predicate = attribute.lessThanOrEqualTo(10) - XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")!) - } + func testLessOrEqualThanOperator() { + let predicate = attribute.lessThanOrEqualTo(10) + XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")!) + } } diff --git a/QueryKitTests/ObjectiveC/QKQuerySetTests.m b/QueryKitTests/ObjectiveC/QKQuerySetTests.m index b45eeac..44b0a20 100644 --- a/QueryKitTests/ObjectiveC/QKQuerySetTests.m +++ b/QueryKitTests/ObjectiveC/QKQuerySetTests.m @@ -21,121 +21,121 @@ @interface QKQuerySetTests : XCTestCase @implementation QKQuerySetTests - (void)setUp { - self.managedObjectContext = [[NSManagedObjectContext alloc] init]; - self.entityDescription = [[NSEntityDescription alloc] init]; + self.managedObjectContext = [[NSManagedObjectContext alloc] init]; + self.entityDescription = [[NSEntityDescription alloc] init]; - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; + NSArray *sortDescriptors = @[ + [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], + [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] + ]; - self.queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; + self.queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; } - (void)testInitializationWithContextAndEntityDescription { - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription]; + QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription]; - XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); - XCTAssertNil(queryset.predicate); - XCTAssertEqualObjects(queryset.sortDescriptors, @[]); + XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); + XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); + XCTAssertNil(queryset.predicate); + XCTAssertEqualObjects(queryset.sortDescriptors, @[]); } - (void)testInitializationWithPredicateAndSortDescriptors { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - XCTAssertEqualObjects(self.queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(self.queryset.entityDescription, self.entityDescription); - XCTAssertEqualObjects(self.queryset.predicate, predicate); - XCTAssertEqualObjects(self.queryset.sortDescriptors, sortDescriptors); + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; + NSArray *sortDescriptors = @[ + [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], + [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] + ]; + + XCTAssertEqualObjects(self.queryset.managedObjectContext, self.managedObjectContext); + XCTAssertEqualObjects(self.queryset.entityDescription, self.entityDescription); + XCTAssertEqualObjects(self.queryset.predicate, predicate); + XCTAssertEqualObjects(self.queryset.sortDescriptors, sortDescriptors); } - (void)testCreationFromFetchRequest { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; + NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:self.entityDescription]; - [fetchRequest setPredicate:predicate]; - [fetchRequest setSortDescriptors:sortDescriptors]; + NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; + [fetchRequest setEntity:self.entityDescription]; + [fetchRequest setPredicate:predicate]; + [fetchRequest setSortDescriptors:sortDescriptors]; - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext fetchRequest:fetchRequest]; + QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext fetchRequest:fetchRequest]; - XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); - XCTAssertEqualObjects(queryset.predicate, predicate); - XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); + XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); + XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); + XCTAssertEqualObjects(queryset.predicate, predicate); + XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); } - (void)testIsEqual { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; + NSArray *sortDescriptors = @[ + [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], + [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] + ]; - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; + QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; - XCTAssertEqualObjects(self.queryset, queryset); - XCTAssertEqual([self.queryset hash], [queryset hash]); + XCTAssertEqualObjects(self.queryset, queryset); + XCTAssertEqual([self.queryset hash], [queryset hash]); } - (void)testCopying { - QKQuerySet *queryset = [self.queryset copy]; - XCTAssertEqualObjects(self.queryset, queryset); + QKQuerySet *queryset = [self.queryset copy]; + XCTAssertEqualObjects(self.queryset, queryset); } - (void)testFilterAddsPredicate { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; - QKQuerySet *filteredQuerySet = [self.queryset filter:predicate]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; + QKQuerySet *filteredQuerySet = [self.queryset filter:predicate]; - XCTAssertEqualObjects(filteredQuerySet.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND age == 28"]); + XCTAssertEqualObjects(filteredQuerySet.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND age == 28"]); } - (void)testExcludeAddsPredicate { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; - QKQuerySet *queryset = [self.queryset exclude:predicate]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; + QKQuerySet *queryset = [self.queryset exclude:predicate]; - XCTAssertEqualObjects(queryset.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND (NOT age == 28)"]); + XCTAssertEqualObjects(queryset.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND (NOT age == 28)"]); } - (void)testOrderBy { - NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; - QKQuerySet *queryset = [self.queryset orderBy:sortDescriptors]; + NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; + QKQuerySet *queryset = [self.queryset orderBy:sortDescriptors]; - XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); + XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); } - (void)testReverse { - QKQuerySet *reversedQueryset = [self.queryset reverse]; + QKQuerySet *reversedQueryset = [self.queryset reverse]; - NSArray *reversedSortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES] - ]; + NSArray *reversedSortDescriptors = @[ + [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO], + [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES] + ]; - XCTAssertEqualObjects(reversedQueryset.sortDescriptors, reversedSortDescriptors); + XCTAssertEqualObjects(reversedQueryset.sortDescriptors, reversedSortDescriptors); } - (void)testFetchRequest { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - NSFetchRequest *fetchRequest = [self.queryset fetchRequest]; - - XCTAssertEqualObjects(fetchRequest.entityName, self.entityDescription.name); - XCTAssertEqualObjects(fetchRequest.predicate, predicate); - XCTAssertEqualObjects(fetchRequest.sortDescriptors, sortDescriptors); - XCTAssertEqual(fetchRequest.fetchOffset, 1); - XCTAssertEqual(fetchRequest.fetchLimit, 3); + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; + NSArray *sortDescriptors = @[ + [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], + [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] + ]; + + NSFetchRequest *fetchRequest = [self.queryset fetchRequest]; + + XCTAssertEqualObjects(fetchRequest.entityName, self.entityDescription.name); + XCTAssertEqualObjects(fetchRequest.predicate, predicate); + XCTAssertEqualObjects(fetchRequest.sortDescriptors, sortDescriptors); + XCTAssertEqual(fetchRequest.fetchOffset, 1); + XCTAssertEqual(fetchRequest.fetchLimit, 3); } @end diff --git a/QueryKitTests/ObjectiveC/QKQuerySetTests.swift b/QueryKitTests/ObjectiveC/QKQuerySetTests.swift index e301b89..4cda03a 100644 --- a/QueryKitTests/ObjectiveC/QKQuerySetTests.swift +++ b/QueryKitTests/ObjectiveC/QKQuerySetTests.swift @@ -10,28 +10,28 @@ import XCTest import QueryKit class QKQuerySetConversionTests: XCTestCase { - var qkQueryset:QKQuerySet! - var queryset:QuerySet! + var qkQueryset:QKQuerySet! + var queryset:QuerySet! - override func setUp() { - super.setUp() + override func setUp() { + super.setUp() - let context = NSManagedObjectContext() - context.persistentStoreCoordinator = persistentStoreCoordinator() - let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext:context) - let predicate = NSPredicate(format: "name == 'Kyle'") - let sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] + let context = NSManagedObjectContext() + context.persistentStoreCoordinator = persistentStoreCoordinator() + let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext:context) + let predicate = NSPredicate(format: "name == 'Kyle'") + let sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] - qkQueryset = QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:NSMakeRange(1, 4)) - queryset = QuerySet(context, "Person") - queryset = queryset.filter(predicate!).orderBy(sortDescriptors)[1..<5] - } + qkQueryset = QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:NSMakeRange(1, 4)) + queryset = QuerySet(context, "Person") + queryset = queryset.filter(predicate!).orderBy(sortDescriptors)[1..<5] + } - func testConvertingQuerySetToQKQuerySet() { - XCTAssertEqual(queryset.asQKQuerySet(), qkQueryset) - } + func testConvertingQuerySetToQKQuerySet() { + XCTAssertEqual(queryset.asQKQuerySet(), qkQueryset) + } - func testConvertingQKQuerySetToQuerySet() { - XCTAssertEqual(qkQueryset.asQuerySet(), queryset) - } + func testConvertingQKQuerySetToQuerySet() { + XCTAssertEqual(qkQueryset.asQuerySet(), queryset) + } } diff --git a/QueryKitTests/QueryKitTests.swift b/QueryKitTests/QueryKitTests.swift index bb5ad5e..a3dd52d 100644 --- a/QueryKitTests/QueryKitTests.swift +++ b/QueryKitTests/QueryKitTests.swift @@ -10,39 +10,39 @@ import XCTest import QueryKit @objc(Person) class Person : NSManagedObject { - @NSManaged var name:String + @NSManaged var name:String - class var entityName:String { - return "Person" - } + class var entityName:String { + return "Person" + } } extension Person { - class func create(context:NSManagedObjectContext) -> Person { - return NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as Person - } + class func create(context:NSManagedObjectContext) -> Person { + return NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as Person + } } func managedObjectModel() -> NSManagedObjectModel { - let personEntity = NSEntityDescription() - personEntity.name = Person.entityName - personEntity.managedObjectClassName = "Person" + let personEntity = NSEntityDescription() + personEntity.name = Person.entityName + personEntity.managedObjectClassName = "Person" - let personNameAttribute = NSAttributeDescription() - personNameAttribute.name = "name" - personNameAttribute.attributeType = NSAttributeType.StringAttributeType - personNameAttribute.optional = false - personEntity.properties = [personNameAttribute] + let personNameAttribute = NSAttributeDescription() + personNameAttribute.name = "name" + personNameAttribute.attributeType = NSAttributeType.StringAttributeType + personNameAttribute.optional = false + personEntity.properties = [personNameAttribute] - let model = NSManagedObjectModel() - model.entities = [personEntity] + let model = NSManagedObjectModel() + model.entities = [personEntity] - return model + return model } func persistentStoreCoordinator() -> NSPersistentStoreCoordinator { - let model = managedObjectModel() - let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model) - persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) - return persistentStoreCoordinator + let model = managedObjectModel() + let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model) + persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) + return persistentStoreCoordinator } diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index f816f9b..696a2be 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -10,224 +10,224 @@ import XCTest import QueryKit class QuerySetTests: XCTestCase { - var context:NSManagedObjectContext! - var queryset:QuerySet! + var context:NSManagedObjectContext! + var queryset:QuerySet! - override func setUp() { - super.setUp() + override func setUp() { + super.setUp() - context = NSManagedObjectContext() - context.persistentStoreCoordinator = persistentStoreCoordinator() + context = NSManagedObjectContext() + context.persistentStoreCoordinator = persistentStoreCoordinator() - for name in ["Kyle", "Orta", "Ayaka", "Mark", "Scott"] { - let person = Person.create(context) - person.name = name - } + for name in ["Kyle", "Orta", "Ayaka", "Mark", "Scott"] { + let person = Person.create(context) + person.name = name + } - context.save(nil) + context.save(nil) - queryset = QuerySet(context, "Person") - } + queryset = QuerySet(context, "Person") + } - func testEqualQuerySetIsEquatable() { - XCTAssertEqual(queryset, QuerySet(context, "Person")) - } + func testEqualQuerySetIsEquatable() { + XCTAssertEqual(queryset, QuerySet(context, "Person")) + } - // MARK: Sorting + // MARK: Sorting - func testOrderBySortDescriptor() { - let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - var qs = queryset.orderBy(sortDescriptor) - XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) - } + func testOrderBySortDescriptor() { + let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) + var qs = queryset.orderBy(sortDescriptor) + XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) + } - func testOrderBySortDescriptors() { - let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - var qs = queryset.orderBy([sortDescriptor]) - XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) - } + func testOrderBySortDescriptors() { + let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) + var qs = queryset.orderBy([sortDescriptor]) + XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) + } - func testReverseOrdering() { - let nameSortDescriptor = NSSortDescriptor(key: "name", ascending: true) - let ageSortDescriptor = NSSortDescriptor(key: "age", ascending: true) - let qs = queryset.orderBy([nameSortDescriptor, ageSortDescriptor]).reverse() + func testReverseOrdering() { + let nameSortDescriptor = NSSortDescriptor(key: "name", ascending: true) + let ageSortDescriptor = NSSortDescriptor(key: "age", ascending: true) + let qs = queryset.orderBy([nameSortDescriptor, ageSortDescriptor]).reverse() - XCTAssertEqual(qs.sortDescriptors, [ - NSSortDescriptor(key: "name", ascending: false), - NSSortDescriptor(key: "age", ascending: false), - ]) - } + XCTAssertEqual(qs.sortDescriptors, [ + NSSortDescriptor(key: "name", ascending: false), + NSSortDescriptor(key: "age", ascending: false), + ]) + } - // MARK: Filtering + // MARK: Filtering - func testFilterPredicate() { - let predicate = NSPredicate(format: "name == Kyle")! - var qs = queryset.filter(predicate) - XCTAssertEqual(qs.predicate!, predicate) - } + func testFilterPredicate() { + let predicate = NSPredicate(format: "name == Kyle")! + var qs = queryset.filter(predicate) + XCTAssertEqual(qs.predicate!, predicate) + } - func testFilterPredicates() { - let predicateName = NSPredicate(format: "name == Kyle")! - let predicateAge = NSPredicate(format: "age > 27")! + func testFilterPredicates() { + let predicateName = NSPredicate(format: "name == Kyle")! + let predicateAge = NSPredicate(format: "age > 27")! - var qs = queryset.filter([predicateName, predicateAge]) - XCTAssertEqual(qs.predicate!, NSPredicate(format: "name == Kyle AND age > 27")!) - } + var qs = queryset.filter([predicateName, predicateAge]) + XCTAssertEqual(qs.predicate!, NSPredicate(format: "name == Kyle AND age > 27")!) + } - func testFilterBooleanAttribute() { - let qs = queryset.filter(Attribute("isEmployed")) - XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == YES")!) - } + func testFilterBooleanAttribute() { + let qs = queryset.filter(Attribute("isEmployed")) + XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == YES")!) + } - // MARK: Exclusion + // MARK: Exclusion - func testExcludePredicate() { - let predicate = NSPredicate(format: "name == Kyle")! - var qs = queryset.exclude(predicate) - XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT name == Kyle")!) - } + func testExcludePredicate() { + let predicate = NSPredicate(format: "name == Kyle")! + var qs = queryset.exclude(predicate) + XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT name == Kyle")!) + } - func testExcludePredicates() { - let predicateName = NSPredicate(format: "name == Kyle")! - let predicateAge = NSPredicate(format: "age > 27")! + func testExcludePredicates() { + let predicateName = NSPredicate(format: "name == Kyle")! + let predicateAge = NSPredicate(format: "age > 27")! - var qs = queryset.exclude([predicateName, predicateAge]) - XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT (name == Kyle AND age > 27)")!) - } + var qs = queryset.exclude([predicateName, predicateAge]) + XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT (name == Kyle AND age > 27)")!) + } - func testExcludeBooleanAttribute() { - let qs = queryset.exclude(Attribute("isEmployed")) - XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == NO")!) - } + func testExcludeBooleanAttribute() { + let qs = queryset.exclude(Attribute("isEmployed")) + XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == NO")!) + } - // Fetch Request + // Fetch Request - func testConversionToFetchRequest() { - let predicate = NSPredicate(format: "name == Kyle")! - let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - let qs = queryset.filter(predicate).orderBy(sortDescriptor)[2..<4] + func testConversionToFetchRequest() { + let predicate = NSPredicate(format: "name == Kyle")! + let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) + let qs = queryset.filter(predicate).orderBy(sortDescriptor)[2..<4] - let fetchRequest = qs.fetchRequest + let fetchRequest = qs.fetchRequest - XCTAssertEqual(fetchRequest.entityName!, "Person") - XCTAssertEqual(fetchRequest.predicate!, predicate) -// XCTAssertEqual(fetchRequest.sortDescriptors!, [sortDescriptor]) - XCTAssertEqual(fetchRequest.fetchOffset, 2) - XCTAssertEqual(fetchRequest.fetchLimit, 2) - } + XCTAssertEqual(fetchRequest.entityName!, "Person") + XCTAssertEqual(fetchRequest.predicate!, predicate) + // XCTAssertEqual(fetchRequest.sortDescriptors!, [sortDescriptor]) + XCTAssertEqual(fetchRequest.fetchOffset, 2) + XCTAssertEqual(fetchRequest.fetchLimit, 2) + } - // MARK: Subscripting + // MARK: Subscripting - func testSubscriptingAtIndex() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + func testSubscriptingAtIndex() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - var ayaka = qs[0].object - var kyle = qs[1].object - var mark = qs[2].object - var orta:Person? = qs[3].object - var scott:Person? = qs[4] + var ayaka = qs[0].object + var kyle = qs[1].object + var mark = qs[2].object + var orta:Person? = qs[3].object + var scott:Person? = qs[4] - XCTAssertEqual(ayaka!.name, "Ayaka") - XCTAssertEqual(kyle!.name, "Kyle") - XCTAssertEqual(mark!.name, "Mark") - XCTAssertEqual(orta!.name, "Orta") - XCTAssertEqual(scott!.name, "Scott") - } + XCTAssertEqual(ayaka!.name, "Ayaka") + XCTAssertEqual(kyle!.name, "Kyle") + XCTAssertEqual(mark!.name, "Mark") + XCTAssertEqual(orta!.name, "Orta") + XCTAssertEqual(scott!.name, "Scott") + } - func testSubscriptingRange() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...2] + func testSubscriptingRange() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...2] - XCTAssertEqual(qs.range!.startIndex, 0) - XCTAssertEqual(qs.range!.endIndex, 3) - } + XCTAssertEqual(qs.range!.startIndex, 0) + XCTAssertEqual(qs.range!.endIndex, 3) + } - func testSubscriptingRangeSubscriptsCurrentRange() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - qs = qs[2...5] - qs = qs[2...4] + func testSubscriptingRangeSubscriptsCurrentRange() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + qs = qs[2...5] + qs = qs[2...4] - XCTAssertEqual(qs.range!.startIndex, 4) - XCTAssertEqual(qs.range!.endIndex, 5) - } - - // MARK: Getters + XCTAssertEqual(qs.range!.startIndex, 4) + XCTAssertEqual(qs.range!.endIndex, 5) + } - func testFirst() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - XCTAssertEqual(qs.first!.name, "Ayaka") - } + // MARK: Getters - func testLast() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - XCTAssertEqual(qs.last!.name, "Scott") - } + func testFirst() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + XCTAssertEqual(qs.first!.name, "Ayaka") + } - // MARK: Conversion + func testLast() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + XCTAssertEqual(qs.last!.name, "Scott") + } - func testConversionToArray() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var people = qs.array().objects + // MARK: Conversion - XCTAssertEqual(people!.count, 2) - } + func testConversionToArray() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + var people = qs.array().objects - func testConversionToArrayWithoutError() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var people = qs.array() as [Person]? + XCTAssertEqual(people!.count, 2) + } - XCTAssertEqual(people!.count, 2) - } + func testConversionToArrayWithoutError() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + var people = qs.array() as [Person]? - // MARK: Count + XCTAssertEqual(people!.count, 2) + } - func testCount() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var count = qs.count().count + // MARK: Count - XCTAssertEqual(count!, 2) - } + func testCount() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + var count = qs.count().count - func testCountWithoutError() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var count = qs.count() as Int? + XCTAssertEqual(count!, 2) + } - XCTAssertEqual(count!, 2) - } + func testCountWithoutError() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + var count = qs.count() as Int? - // MARK: Exists + XCTAssertEqual(count!, 2) + } - func testExistsReturnsTrueWithMatchingObjects() { - let qs = queryset.filter(NSPredicate(format: "name == %@", "Kyle")!) - XCTAssertTrue(qs.exists()!) - } + // MARK: Exists - func testExistsReturnsFalseWithNoMatchingObjects() { - let qs = queryset.filter(NSPredicate(format: "name == %@", "None")!) - XCTAssertFalse(qs.exists()!) - } + func testExistsReturnsTrueWithMatchingObjects() { + let qs = queryset.filter(NSPredicate(format: "name == %@", "Kyle")!) + XCTAssertTrue(qs.exists()!) + } - // MARK: Deletion + func testExistsReturnsFalseWithNoMatchingObjects() { + let qs = queryset.filter(NSPredicate(format: "name == %@", "None")!) + XCTAssertFalse(qs.exists()!) + } - func testDelete() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + // MARK: Deletion - var deletedCount = qs[0...1].delete().count - var count = qs.count() as Int? + func testDelete() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - XCTAssertEqual(deletedCount, 2) - XCTAssertEqual(count!, 3) - } + var deletedCount = qs[0...1].delete().count + var count = qs.count() as Int? + + XCTAssertEqual(deletedCount, 2) + XCTAssertEqual(count!, 3) + } - // MARK: Sequence - - func testSequence() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - var objects = [Person]() - - for object in qs { - objects.append(object) - } - - XCTAssertEqual(objects.count, 5) + // MARK: Sequence + + func testSequence() { + var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + var objects = [Person]() + + for object in qs { + objects.append(object) } + + XCTAssertEqual(objects.count, 5) + } } From 5614fbca149ea8d63d88be7451c81f05b3b74bc5 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 4 Apr 2015 22:27:45 +0100 Subject: [PATCH 12/71] [QuerySet] Rename generic to ModelType --- QueryKit/Attribute.swift | 4 ++-- QueryKit/QuerySet.swift | 44 ++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index f47c335..a4e201b 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -105,11 +105,11 @@ prefix public func ! (left: Attribute) -> NSPredicate { } public extension QuerySet { - public func filter(attribute:Attribute) -> QuerySet { + public func filter(attribute:Attribute) -> QuerySet { return filter(attribute == true) } - public func exclude(attribute:Attribute) -> QuerySet { + public func exclude(attribute:Attribute) -> QuerySet { return filter(attribute == false) } } diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 172cc0d..51d7db7 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -15,7 +15,7 @@ import CoreData /// Represents a lazy database lookup for a set of objects. -public class QuerySet : SequenceType, Equatable { +public class QuerySet : SequenceType, Equatable { /// Returns the managed object context that will be used to execute any requests. public let context:NSManagedObjectContext @@ -37,7 +37,7 @@ public class QuerySet : SequenceType, Equatable { self.entityName = entityName } - public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { + public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { self.context = queryset.context self.entityName = queryset.entityName @@ -52,17 +52,17 @@ public class QuerySet : SequenceType, Equatable { // MARK: Sorting /// Returns a new QuerySet containing objects ordered by the given sort descriptor. - public func orderBy(sortDescriptor:NSSortDescriptor) -> QuerySet { + public func orderBy(sortDescriptor:NSSortDescriptor) -> QuerySet { return orderBy([sortDescriptor]) } /// Returns a new QuerySet containing objects ordered by the given sort descriptors. - public func orderBy(sortDescriptors:[NSSortDescriptor]) -> QuerySet { + public func orderBy(sortDescriptors:[NSSortDescriptor]) -> QuerySet { return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:range) } /// Reverses the ordering of the QuerySet - public func reverse() -> QuerySet { + public func reverse() -> QuerySet { func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { #if os(OSX) && COCOAPODS return NSSortDescriptor(key: sortDescriptor.key()!, ascending: !sortDescriptor.ascending) @@ -77,7 +77,7 @@ public class QuerySet : SequenceType, Equatable { // MARK: Filtering /// Returns a new QuerySet containing objects that match the given predicate. - public func filter(predicate:NSPredicate) -> QuerySet { + public func filter(predicate:NSPredicate) -> QuerySet { var futurePredicate = predicate if let existingPredicate = self.predicate { @@ -88,26 +88,26 @@ public class QuerySet : SequenceType, Equatable { } /// Returns a new QuerySet containing objects that match the given predicates. - public func filter(predicates:[NSPredicate]) -> QuerySet { + public func filter(predicates:[NSPredicate]) -> QuerySet { let newPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) return filter(newPredicate) } /// Returns a new QuerySet containing objects that exclude the given predicate. - public func exclude(predicate:NSPredicate) -> QuerySet { + public func exclude(predicate:NSPredicate) -> QuerySet { let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [predicate]) return filter(excludePredicate) } /// Returns a new QuerySet containing objects that exclude the given predicates. - public func exclude(predicates:[NSPredicate]) -> QuerySet { + public func exclude(predicates:[NSPredicate]) -> QuerySet { let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) return exclude(excludePredicate) } // MARK: Subscripting - public subscript(index: Int) -> (object:T?, error:NSError?) { + public subscript(index: Int) -> (object:ModelType?, error:NSError?) { get { var request = fetchRequest request.fetchOffset = index @@ -115,7 +115,7 @@ public class QuerySet : SequenceType, Equatable { var error:NSError? if let items = context.executeFetchRequest(request, error:&error) { - return (object:items.first as T?, error:error) + return (object:items.first as ModelType?, error:error) } else { return (object: nil, error: error) } @@ -123,13 +123,13 @@ public class QuerySet : SequenceType, Equatable { } /// Returns the object at the specified index. - public subscript(index: Int) -> T? { + public subscript(index: Int) -> ModelType? { get { return self[index].object } } - public subscript(range:Range) -> QuerySet { + public subscript(range:Range) -> QuerySet { get { var fullRange = range @@ -143,13 +143,13 @@ public class QuerySet : SequenceType, Equatable { // Mark: Getters - public var first: T? { + public var first: ModelType? { get { return self[0].object } } - public var last: T? { + public var last: ModelType? { get { return reverse().first } @@ -170,13 +170,13 @@ public class QuerySet : SequenceType, Equatable { return request } - public func array() -> (objects:([T]?), error:NSError?) { + public func array() -> (objects:([ModelType]?), error:NSError?) { var error:NSError? - var objects = context.executeFetchRequest(fetchRequest, error:&error) as? [T] + var objects = context.executeFetchRequest(fetchRequest, error:&error) as? [ModelType] return (objects:objects, error:error) } - public func array() -> [T]? { + public func array() -> [ModelType]? { return array().objects } @@ -217,7 +217,7 @@ public class QuerySet : SequenceType, Equatable { /// Deletes all the objects matching the QuerySet. public func delete() -> (count:Int, error:NSError?) { - var result = array() as (objects:([T]?), error:NSError?) + var result = array() as (objects:([ModelType]?), error:NSError?) var deletedCount = 0 if let objects = result.objects { @@ -233,8 +233,8 @@ public class QuerySet : SequenceType, Equatable { // MARK: Sequence - public func generate() -> IndexingGenerator> { - var result = self.array() as (objects:([T]?), error:NSError?) + public func generate() -> IndexingGenerator> { + var result = self.array() as (objects:([ModelType]?), error:NSError?) if let objects = result.objects { return objects.generate() @@ -244,7 +244,7 @@ public class QuerySet : SequenceType, Equatable { } } -public func == (lhs: QuerySet, rhs: QuerySet) -> Bool { +public func == (lhs: QuerySet, rhs: QuerySet) -> Bool { let context = lhs.context == rhs.context let entityName = lhs.entityName == rhs.entityName let sortDescriptors = lhs.sortDescriptors == rhs.sortDescriptors From 4516945240342985baebda1d3cb674ccb7cbc1d0 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 4 Apr 2015 22:30:08 +0100 Subject: [PATCH 13/71] [Attribute] Rename type to AttributeType --- QueryKit/Attribute.swift | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index a4e201b..c8bfe00 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -8,7 +8,7 @@ import Foundation -public struct Attribute : Equatable { +public struct Attribute : Equatable { public let name:String public init(_ name:String) { @@ -34,7 +34,7 @@ public struct Attribute : Equatable { return NSSortDescriptor(key: name, ascending: false) } - func expressionForValue(value:T) -> NSExpression { + func expressionForValue(value:AttributeType) -> NSExpression { // TODO: Find a cleaner implementation if let value = value as? NSObject { return NSExpression(forConstantValue: value as NSObject) @@ -56,43 +56,43 @@ public struct Attribute : Equatable { } } -public func == (lhs: Attribute, rhs: Attribute) -> Bool { +public func == (lhs: Attribute, rhs: Attribute) -> Bool { return lhs.name == rhs.name } -public func == (left: Attribute, right: T) -> NSPredicate { +public func == (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression == left.expressionForValue(right) } -public func != (left: Attribute, right: T) -> NSPredicate { +public func != (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression != left.expressionForValue(right) } -public func > (left: Attribute, right: T) -> NSPredicate { +public func > (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression > left.expressionForValue(right) } -public func >= (left: Attribute, right: T) -> NSPredicate { +public func >= (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression >= left.expressionForValue(right) } -public func < (left: Attribute, right: T) -> NSPredicate { +public func < (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression < left.expressionForValue(right) } -public func <= (left: Attribute, right: T) -> NSPredicate { +public func <= (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression <= left.expressionForValue(right) } -public func ~= (left: Attribute, right: T) -> NSPredicate { +public func ~= (left: Attribute, right: AttributeType) -> NSPredicate { return left.expression ~= left.expressionForValue(right) } -public func << (left: Attribute, right: [T]) -> NSPredicate { +public func << (left: Attribute, right: [AttributeType]) -> NSPredicate { return left.expression << NSExpression(forConstantValue: right._asCocoaArray()) } -public func << (left: Attribute, right: Range) -> NSPredicate { +public func << (left: Attribute, right: Range) -> NSPredicate { let rightExpression = NSExpression(forConstantValue: [right.startIndex, right.endIndex]._asCocoaArray()) return NSComparisonPredicate(leftExpression: left.expression, rightExpression: rightExpression, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.BetweenPredicateOperatorType, options: NSComparisonPredicateOptions(0)) From 2c4c64975c900695ee19f6dcbc31b1da19e0457d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 4 Apr 2015 22:37:11 +0100 Subject: [PATCH 14/71] Sprinkle some extra documentation --- QueryKit/Attribute.swift | 6 ++++++ QueryKit/Expression.swift | 2 ++ QueryKit/ObjectiveC/QKAttribute.h | 2 ++ QueryKit/ObjectiveC/QKQuerySet.h | 1 + QueryKit/Predicate.swift | 3 +++ QueryKit/QuerySet.swift | 1 + 6 files changed, 15 insertions(+) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index c8bfe00..93e4360 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -8,6 +8,7 @@ import Foundation +/// An attribute, representing an attribute on a model public struct Attribute : Equatable { public let name:String @@ -20,16 +21,19 @@ public struct Attribute : Equatable { self.init(".".join(attributes)) } + /// Returns an expression for the attribute public var expression:NSExpression { return NSExpression(forKeyPath: name) } // MARK: Sorting + /// Returns an ascending sort descriptor for the attribute public func ascending() -> NSSortDescriptor { return NSSortDescriptor(key: name, ascending: true) } + /// Returns a descending sort descriptor for the attribute public func descending() -> NSSortDescriptor { return NSSortDescriptor(key: name, ascending: false) } @@ -56,6 +60,8 @@ public struct Attribute : Equatable { } } + +/// Returns true if two attributes have the same name public func == (lhs: Attribute, rhs: Attribute) -> Bool { return lhs.name == rhs.name } diff --git a/QueryKit/Expression.swift b/QueryKit/Expression.swift index 6180570..fa635a5 100644 --- a/QueryKit/Expression.swift +++ b/QueryKit/Expression.swift @@ -8,10 +8,12 @@ import Foundation +/// Returns an equality predicate for the two given expressions public func == (left: NSExpression, right: NSExpression) -> NSPredicate { return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } +/// Returns an inequality predicate for the two given expressions public func != (left: NSExpression, right: NSExpression) -> NSPredicate { return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) } diff --git a/QueryKit/ObjectiveC/QKAttribute.h b/QueryKit/ObjectiveC/QKAttribute.h index 1f82b41..09e5fa3 100644 --- a/QueryKit/ObjectiveC/QKAttribute.h +++ b/QueryKit/ObjectiveC/QKAttribute.h @@ -33,6 +33,7 @@ @end +/// Predicates @interface QKAttribute (Predicate) /** Returns a predicate for an equality comparison against the supplied value @@ -200,6 +201,7 @@ @end +/// Sorting @interface QKAttribute (Sorting) /** Returns an ascending sort descriptor for this attribute */ diff --git a/QueryKit/ObjectiveC/QKQuerySet.h b/QueryKit/ObjectiveC/QKQuerySet.h index ff37b3c..deed153 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.h +++ b/QueryKit/ObjectiveC/QKQuerySet.h @@ -147,6 +147,7 @@ @end +/// Creating a queryset for a managed object @interface NSManagedObject (QKQuerySet) /// Returns a queryset for this object in the given context. diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index 75b2fe7..170de98 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -8,14 +8,17 @@ import Foundation +/// Returns an and predicate from the given predicates public func && (left: NSPredicate, right: NSPredicate) -> NSPredicate { return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [left, right]) } +/// Returns an or predicate from the given predicates public func || (left: NSPredicate, right: NSPredicate) -> NSPredicate { return NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [left, right]) } +/// Returns a predicate reversing the given predicate prefix public func ! (left: NSPredicate) -> NSPredicate { return NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [left]) } diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 51d7db7..4b7c436 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -244,6 +244,7 @@ public class QuerySet : SequenceType, Equatable { } } +/// Returns true if the two given querysets are equivilent public func == (lhs: QuerySet, rhs: QuerySet) -> Bool { let context = lhs.context == rhs.context let entityName = lhs.entityName == rhs.entityName From b1f96a76f5dd65fd1bc9e6022935a383d7062f8d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 4 Apr 2015 22:44:22 +0100 Subject: [PATCH 15/71] [QuerySet] Break into extensions --- QueryKit/QuerySet.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 4b7c436..af043e2 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -48,7 +48,10 @@ public class QuerySet : SequenceType, Equatable { self.predicate = predicate self.range = range } +} +/// Methods which return a new queryset +extension QuerySet { // MARK: Sorting /// Returns a new QuerySet containing objects ordered by the given sort descriptor. @@ -104,7 +107,10 @@ public class QuerySet : SequenceType, Equatable { let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) return exclude(excludePredicate) } +} +/// Functions for evauluating a QuerySet +extension QuerySet { // MARK: Subscripting public subscript(index: Int) -> (object:ModelType?, error:NSError?) { From 304f484c55efaf3594f585cb6038c4849e4eb8b7 Mon Sep 17 00:00:00 2001 From: "Florian R. Hanke" Date: Tue, 7 Apr 2015 14:36:20 +0200 Subject: [PATCH 16/71] Fix plural usage. Maybe a simple rule helps: if it's a plural, you never use an apostrophe. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da70de2..e065190 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,11 @@ Using slicing, you can limit your QuerySet to a certain number of results. Person.queryset(context)[0..<10] ``` -**NOTE**: *Remember, QuerySet’s are lazily evaluated. Slicing doesn’t evaluate the query.* +**NOTE**: *Remember, QuerySets are lazily evaluated. Slicing doesn’t evaluate the query.* #### Ordering -You can order a queryset's results by using the `orderBy` method which accepts +You can order a QuerySet's results by using the `orderBy` method which accepts a collection of sort descriptors: ```swift From 05335e6c739ae968b1c9a9ff0d66f3228e3c4ab0 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 1 Jun 2015 13:59:43 -0700 Subject: [PATCH 17/71] [README] Include logo --- QueryKit.png | Bin 0 -> 21120 bytes README.md | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 QueryKit.png diff --git a/QueryKit.png b/QueryKit.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ab70d835bb82e5b904502568f6372f8ea6cff8 GIT binary patch literal 21120 zcmV)?K!U%CP)Pyg07*naRCodHeFuPCRn`A1)64c`H@z1Kfnc)PBm@nJq9}e+5(|i^G*OgJ5Sl_|TMo!On4o%`lK$j*DW zoO|xM_jm5Oo#)s?y#y94SYYE8ta3%Uc8?-8Rm!f)A-roy1t+K;F4$hfE8#I5FAP^X zv6{2lt2xf*R|Ubwi*`51sR}2>g1oB8iW)s8$ns%Dkq&dbxR-M{KjGXZNBL-|i*G$} zRI%HS*hGS(lwcLl}%DP zu8LP;qdCzvoD&2W;Mfg?>J=Pb4nPl?Q#nuWj17~yrQG+;1f&D2= z31}r>n7kD&R};VZfU|7gm&Xcr$3#JN)^dV40f2c5C)g?h$kl?wBLYGJtXlD@3IJP? zL0&r85qkvi*%G0a7D-K461*Uq>2r|23WkId3kG??)}+S52YAu;juPqE1xjh7+O}`^ z#=BhHl6%PL6Kjl*n2+7+e=>-10%=>P684&4OjwVhSKnMOz!#HlBA6 zIbEx9_(5_an zyJ0w9>kH#R8GHJY09pqyhG4UkZjc%Y9f3iFwXziY2jBL|zZ+K69qo$(^G{y_OaY`X zt6oFS2)te9@Q?l+RNQZZX?uoX_m-k*4})LWq3<;w^XOXwL>Y(<&1#B;_i}RNc`nxR zRL7P_*EOyVurY(aMR?p0OaUBMJjeH(z3jtTg1hV+Fdu#%Z*z{*OjzvBGSDAia{coq z-2|8wQKGOML5XcvV&T83ZB2jQc-Qp3{iDcYF$Iue9hiB=vmSBWsb3PDzVC8^{Y=5> zai}(X*{p`zAF{Q4y!x$` z^E(QR(}H4$DS%#zW9FUjPOy81U(JcmO9ZF4imZo+1v>00dc#y%;K02wEMCCRXN={@Ko zJP>Yr>9KA1U4k2x*rQ8;DF9s%bxSu?b7kYM=AHg40r=Gn_}0Nlf+ENUDOJoZu#DGcz5YfVTtZ+oV#aJdBsruVX)8+gN0H=R%4N;)Q+aR>I0Lu7emf_ z%41O~fZ2ifCJX-RpK^B3*9FlokmD}u)A;_K`RUv-p}pX_{;hS&uO=A zhI`IgQ7Hg4_qpL`{7|)fZiWRsRj`r_Ou_=)Tiolr55RV0RgDE7q~+Yj(^$t@tU7CKD5YE2bo$*0nA#l_X4}S{6XI79R^E3 z`&r~H8k0bZ1Yp}St{qUq9dAl)`@X*^aN>VcLQwl@2?c=Dd&=-Leg?~UZ-8kXfi38v zwmud#<8Ztio@jhn2_3z@VezQP3!2$9nS*nh>3(p#u23`UZ=$E-5;#hm*DlDQJ5P-J z!ju3`9m4>j4-~=q!_WMY+dXyE8^;=6q`HquwFOYS?4wVMz9D~v(|IN`lfN)QV@a;C zO91NzE>NP&!xaq$Zy_J`+^Z012Zr0=(7Y@PQjZrn!baVaUQNN-om(&ab)&?4CT*Ib4 z1%rL(Y0G)pCLWq9nx%P#RfBLDst60uzA)m9Yh3$J^R9sdN2sWvR49N`mwhzG<{$O6 z=q{ZP(=e8U(gC*&K)1r@ueeH@pkuUwu`Tjs}bWZ zRRTCepmZI5RXO_M*9-YR!-Aa!n7M4ne6D2Jzc`zVfj_l&vG0PH09vbpxAH8ZYSKSW zzH#f&LS?uhEr3~f?p$E^4}XfYyN1HqZG|d3#ut-7pAsOJK(KY4eCWUh8}FTVsLu#_ z4p49w!0bC3Pq+JrG4SWPBCzCgBLTDoL{Hf~p=S8%lLK!RoF!0D7C>EK`y9S}^gjig zyN0dq%T0x3R0l@_xRFQ>wY;u2?>xVd#smt+0+@Bzu9JkaF;6k@4^9PTspeJ!IDIX8 z%0JClPI#j3niooPn_BwR3t}C>>^pal6a6($Lw{)kYx&bJJQk8J3E;)0a8S(z)m<^U z?6g_`YFfK`(039Jx&<(E>84?Vzw#dd{;6!LkFE;MxXoMwWK6(Ud4bRW+5d$z=?A?F zKBx)+O(93c*uTPd-c#8kpUf*0i$SLZlxP?%f%3~|uROeLuyZhY8ff7van9^B|04J* zzsbO##cBYDS>lzCJnUJ=OE2J0oOn8=owR~og?m#JI1^8XU-W=~>>`!8JO}cIS1B3IVQzdf3S?xWCmfK6Jm!LKz6)PvHSeYn-9Ewl0!7lgBOEsKm9}XvAxFNh7=e5bBpmG4kfETPVrC^9MqhF$+IW-*XXu4q2(orvD6gf+Q z2SowY-LwBYf@jDdpmh=OwpR9}BLM(BwCFql9uUvL#g=%JO*=U5RAb>iKw%TK)cfR6 z^A6r$b}-!ZQRmdVPj6q%aRVA?n!E59Ze_+-OE^U>;RSV~>Z%y8%8_YsoAL=zexpH| zjOOi58}bH6vH?%15LlU}Q=%A#oH{Ipo20HipWk@vw0F{tm#uJlR{(W)?LI^B*E|Ci z*T=5s>Z2I(=qcE1&ItlsQUSXlRpk>{8Tl>%ZJinm)k~_ptMt|H?q54dciqpp_Mc_8 zA=5_+qU%#I&plJ+#rdEJCJT0t4|&$ET1Wkp)UW6x)5YhFmy{}z&Ub@tAD^`?aLSQ< zN+7QaU}m6kw7qoHe|U#?EL-B+OEDwpZEzMn*za&NO&6R=zZGQlnj&?*YHK?9?)v-Z z9qT1#Avg#JLC zpZq?Arm_j0dCM!MLfPb6!R9@evpdfQYi0_$gj0%=?m~(bivANVfmmnL9UE_ktLyXh zji@|H}FVG@W_Sri$_15^#pn#m=^^wd&Rzmg172P zNS_V*fe>&Y56_VU6TbyU*`HBk9glWyTK87t>P6bAB6U zDQ59D=mX>Zjchi7)C-uwIT&f(^XV;tX}fY==s8yavu@iu#a1=pbuj&g7W<7o2znSb z#{r*D)M)TgDSG75&9_hgFxQ1#sPv~TT;=f3ocmeTQF0~7=8Mn|cCcHVp_L>Xhg#PN z`(F9d`ui8<^bEY5DuA(<{@FG3q^~?@^HzMem>2t)z>jr(phiQ#k-Cokb#q_}%*nII zkU-tCkLU27@@rr$Mk00LXlo&b$21>xEem>D>y zVadqXa#g-LQvkKgcFnVujQBU$ye?cIQdAF&>XW(MXt0?Jcm7&vI`q)G`|>-#OS`=B z+BY~-Ybh*1JR9l|OpFx8@JLdzkr|Un=le?2`}1>khCogfz-c$X@0Y8q|0B3dPc63A zAMcEV$|}Qj-rv-&rn?#fCw!1ps_Y{Z2?%pm?qA3`N`3+x#!ggYFntKikBjNS^#M}H zk>57lT>brAidtu7&#$xLC6LTNt^5L$yO-lI4t@TUBznqH#D@K~r7e80- zt(tQ^XZKtOmX)`t8Wmh4A_%hDzW@9UOUFNx?efpM0+_XY*J*a&$X8+I3M~IBjy2)L z+?T>ZHQaSy=kEXB+xXBKo!KrZMvvoWE&FJ;=&iU{be4P?XOxPiYY7+N!pu?d1GVYB zdD-p?Wc5U#nO8jPu~kofLU4M=6vdPuF5A`Cao5AP&WmAN=VMJ9A1%JlYM!*yf!BVu z-#%>0lkU>tA?Rw=2{xCbDE5=U7@FwvR;sXIV*ji6{a-f4omC5RWKZyaAb>HB6)0nEDd{VAe<eGw>jd0Y3@H#SDlROxsr7B|5#<20u>k z;gwI3wzX>0o--Nv2UKSU9Qj>XQ&E3I#Z_uo^A#{2(1FutR({aZfy+nd*0`r!k*$1Y z#R8~XzWW^51Xf8N;tqUNTfg#@eFGKnfGq&r=F7WE?}X7X>w+Kq`*7G6^uKPZ zziG%-4EzJFcG-`=`L;1{a%~@;rGz{GgH{@zr(ng094+qj)o??GEy+gy2CM+2nz5G) zuF_9g^?(nYg5l&?tJHDu;`+tI?#qVI8I9aXU_;>4-LXR({zvI-UM1L}I{;laD?Yek z3Km9vxAu-5wFAxHfTjWG1-1_5y)}=(xmBfBob$(3eVi0MD219Y+_-e?pd8vb&;l;D z_y^y5EK*wLea2ory#xja=V)7ut=277amSzyay4xK%PVo4eZQXpSpbr|`bRJgGs=o{ z{xHXk2X*XLJNJKiB5VLeSRet z+!O2Af8NHQOlmAV4jD)Nk-)~AhOUr;Ew^iTD)g($_b1sr#DObd;7%795WHpLH81pQ z5k$YFVJ{zY4KDh@E2FIPkPR0wzp4h0Ua5Kw%rDHCJxyNd&jQk4@nCtIs{&T}E!&X|OBCuSfBLTdBPifirEg0}^ zBHOytiB#ZW$SKNp_h)7;zj$sYtfs91PQG`mm$SPsw+#64*yT{`I@{6KAA`WGF_@7_ z$rpLphC5H%s)U-agq<~#CDsVwx&WKgW^I<(FXL&lD@H`a`V`hjt!` zcI~_Dt(8;RK^~dZ7z>4MSTgpXO1R^0vgF$W`NC;=*q8t1xdE7_PxDDn0R#d99M60i zSxk{8;eri@8$?t^k%LFC*>d~z_X?Iz##mk?aCGmcWlHeat9Zx@^$(nw%sag$vb*Zy zbn}vy0;m%%J{4|j`HU47{*aY^;nv@7ymic~bcMviSyuwP9y}+)cOLpaj0YUD!gv5q zZwe0Q#dX(gC`qT((oz7NyX0b+Hi0v*Gn!&dC;hyJ!4qTTP}?@CdGFG^Cd?8mXbG%` zOE~3F^G#a)rhAbPcF}pecY->6SXxtpeJX(YaPAu1;Ccb|eSe(qmt$cyeC&st@0rzB z&^3}Vmv;$lTs-ElFdpz%v=C{3@B&)S?!5%^(Wf@+QvpQF#(ojj8pD=fiE6pv0TD9X z&)2YYeAZ4>rCK12`EC*jx9(dEcR22+y(>VL2isg{&R+iEq;8o^ap+S4a5nGP$$5Aw z5o!7qV37ov{yRcP-(Nu!-;CG%N?_|)IG&)Xdf zr!8CsXWI4t99IGGo}vE(=D(lj3mI{>pBim{dh^oJ?EL=T>jCr8C9rz+BAE|&EK#IT zkmdzKxLhBW2cPUcb@t5T74C5qKtSL{=lL{`{NqV5YBby-g(<&Y{_A=HZY8 zMG8Jt9~k)UDZL4gxm#QUt$Tl~gxfx$RtdlcA>Qs1Rl)P6-b$)R1u!S@{uoZQ)v7X` zH(g`vFNZr1@-0Vx+grw&JCi_P5@=XacT|Z6e?{{i7@Q4IMf=$^ulQY$CkOYa02Ei* zrv8U*l zy+;KAqo1GW1UeT&kiLJU^QaOz^821L%-om+GLZnW0%F16lXD|8iC8FMVNnoo_qc41 zvQPKKQa1%K<(~KbFamHItxJEg^@n>3pW1la^u0Z0n7J_tWGsPL^CPfN;26za0nYCH zTu=G#rT}~~`zdfh!YC?F{(%iYYAh61I*+l|zo*h>ZvBz~HYTbZ`8%GwN8>{_^6_FF z928QK%6~TnAUb^WaO9B2BfrU-|47%`je*HqQ!~oGnFIzR0U_M+MwHNkGVfq)BW1V3hsELoN!f5O+)jIwVgfq_V1&0io8nWV4yY*V6PEuWs?(SlB@t!ZVso?H~&w}|5$i?P};I7F>~ylNg&%2P?Yd$ z8oS6it|!`Eyx=OSO_YhL0H!SrI5?YYI-TY}PFlpCZ44};bM10siLm#AmH^*+;6F+% zbdbhff+{xdDwnh|$W#E%PhC73BtMqE`G1~MqG3gehF&P>n!}j0gamM9ARI3H9~zei zlg8cVnz3L(08S0n9#a9>Ibl330P@nd{Z}9S`zW;UBR2PMlq&npsRUFh^dfCIAp(K* z0AMPQX*+At2tz=o0^n@EnKWuOQ~#*vdv3@`)<|UYN|`wOO=1u-QRTWB;a&ZN@LX5*XWf>mF!Hx50tA)MWyBRyf%_ zCs0!WaQ7b^{XJck!9<|xfn}LWBpBj@t?OuFoAFAw1XizJEyIBmZ*p+vBy|t)EZF?! zR3OR0%+P6mH~^%Ywtfw2Gnn6euZw$kH+2QU7^YeRU{0^YlXt0G8K}T1L7X(j5I#`= zHh0Y!unVeG+V1`%*L_J_+4P@Loa{GW60pTu--aE6owRkERTXadvbo28@qwLAl$B<~ zc!t;T4mTX2ujEU9SxX0|E#Jx-F-C|txkng-=po?JaWvRXe+n*$C9Z)q5xF8 z=S12DGNWwPzLG+F z240Me0+T@hBp}-4g8-&>>c-C?yI?_=VXlSH=vpW2Z!V>71^{O)Vxh+V6&;JkBrtFZ z)HnXT3r?Wk3oB~|PAs1k(At;6)sQ6I0M^{(htV`xQIk&&2A&q~T2$O+2M11xQD742 zrvz|CAaDB!Z=t5?L2Dn5{vST^nim|n z`QJiauF!h6xyq|Y)`9|XmsG(NAgl_a#{|GBKsW@fH5xs1ggW6fhAkxlHPX6|x&d@3 z0a!+33x|%uQNi8{zhHL*{^?NwIP0PcwqS+N!43em6r3o`jKb}u3Ogub#JZw5M5)z} zt7!oJl&u29_FtAFLmHcKHwJr{1O`n4s?*n`($si@q)1cGb51xWyhISfU2se=MXf(% zfUE+PBQ1DV`=FIPOPEOjBp^B*VcPIR_*GRW@AQHNAV-E$XTsnhpsLb0_`)D#ISDAC zt_Vy8l1?=>nS=Ho)&cMw?{W)po=z22GXT1jq0`bujldbBmX&}KIvR#GG|&~LsT&O% z0M63jT^_ffa!MIxJpfJCf)KK7tzsFYMgl@45(NxVHx`9^X;jf=7kEze($|MUi;HJ_ z0H}e9bs1H;n8d4`4E8jAnN(%mQ_E3#={XF%(sz0ZeN}{U+=m2sk+La(g#0LqEP?{y z-P8>Nl1!+SEx=BYJbSf_1Y}OaRcT-Z&^4206o8=eDx7alqxqsR1z?mS`yDh1@Vw6k zHh?&23=A+~7z5y_8^F+%t?C(I-dS`efdNZE;G8ZPkD{_0EeN6v>i{IUQHM4Q0L(2_ zEg5j>F#=2i1C#*ouXe#|AiSM+fRqLyIt*aIEdfF^ZCwC7z8p3(mxIV?(_Dj4$}GuT zNcS1v0hqn$qqsB)K=wgwdW zRplrrO2LpI^L7gN)Z^_Yg5y|clw59*zv5;oF$ttdKnhkle!c9_%@Y+e2EYqt zO8HQ7yGfpsWyvrJbeDkBUqf5_Nh}tXi*RZT6hP=`yBdQXjWn$V01JS(yKTI`3I_t& z!z3_x5`beVC>#GH2EWSlv6!c#6V3x@ZH6ff*jPhXHvk7NmEf_lgIDq_w1ul2 zFcvkDx+C?qf{Qt#Tm;qv2uGpy4^cN0fER-}{L_lP60-aco&-v!P4jU!2b`xtR~MR$ zSxAwVilaLtLfADHmI4dW!4qTuQx*haRR3eMm`nl#lR%V{#=^lgWwad$1{VXuLOSKp ziw~X?75wi%9f3;%THwaOfk`9JvEfWW=(UI^!rA6*DlpHoXUS<2u=$3K7ad*)b(iYk zc%RL27;>QsYajVem{Zg}L@Ur#vUs++APy@psTxWX+l*HWNkEECr)uy#LG-Gkw&Ew5 zz*KF{Bb1E+g3?t0|Bh0@H}Zspe6d$1f&59p?wOIl#Il$Y?puho?M8~)3WjJGngf(Q zc+WWu!t(0LlrhfOwSWYsUA@K!1Lr5=6?N1-pa4X>eJAow_SExIa64QSKwUlv!#2-c zIvHnN(<}i`&B!r;qER$X0V;9~*Zwu3{D}o1yZn1`bscRF(Y^vV12zTuXycvnOSuH> zzFNWVa?&;ch+}5IoKR2x5yZB9fc6i2{fmYsNdy;amW1NPwF1fxe93aN9(?_jGD_W{grV zfw|YMbHf<`b2yo@1wbfyv;bnEPuAZ*57z(d7C_@eXLP}SfCK1B-Gd{VcKc_k1D>{8=qUA~DF<>y(r^X_?4AGm2=cC~rv<+xrCU89f?{E*59Od(jOtD`kft*Uf z=KKQqcg;Qm6o6IuPb$M@C9Uond5*{W1yU zKmt5WJ716kx_Kc9%)=Uh@P9Wye5H98h^YX$)vMu_qsZITZ3@ywhetDuPXE{QB1x7= zQA(ipj-4m+c2}Ju(P#dX0>d+Zcz#o2;l&jIx+>}>Doq<;9lHUl;P~9kK;!7d46=77 zfow@YaFr~A(SNv0lfG56xBy6rg;gck+PeZ!V=WCzGz`P)s4D1saB(wC&yF9|;Kd(yPJzr|;}PJ+rs~ zNR^_^vChbr)cki-0J7AwT~%TqYB!#y2B+X#+ac%>UH)q+;Fhsi;1Za*e8*JI=3WTv z=L?+E-r2+cKlG0`zP(~nb84t=3Se_!RuE1(d4m@z9SDRRDo|Lw-E-dTJ9eCsnql_M zB#?;&M0>@LM5o6~mBzi!gn9S_^R$A);}YBz zHycjumq{Q~3Cy|kgA+uD=UZxw(uF^mVFZ696cxkKwLRs(M+G2v9C}lU1&`9YDiAY@ zRsiSlURbwm=bWB0&fJ&;`jUX+s#wfBJU-ek&rQr1nf_BE@3$)rjfw8YdyfiW^YU2- zd0ARV`VK}&+J4aru)7?btKuhM63{uKNt?_q#P6KtAJ>Ua@7G8}LUF!GBQ8rXHwG5< zXvXxY05HFb6nviId=u8O@L=cG7wYal@D>67ASx|1a4+`Rlj}AQC?Cyb|f6 zdNzP$7Y+=8qr=O1Z^h3S1OoIfa7ZpY_LXG`%vrwYG}!X{L)r)aP%J!J?y+!V(+6wo zk0++%DuA~GpE>|*h+pAtj^ojw!VmUBbAqSz3ti63ub_fq#$;Y4Fy-bq{hYJpLHY;& zG_m36zp6^BcjN8f$9ayc05BdO3q1j20mmUhi^) zMDUcIiVX$z51jq4M1x_uv+cO%KjyPf1<r zx~R_(%Rp8nP`7;dIlQa0>i04 zInuc|tTexnP7$W105&fj_dX|uUlQ!rIBARQ>=Fc<=qdjVn;J}~npiW8Z|3};iQbBH z;2ccLWRR@=m!prryX54SbTXBe0zg81q~i}T7zj)2tg);f&vt_ygG0H}A%B^@q`op8 zVX-jQkwEQ=y%!1I%A2&+esnMRF-rvp{~}!>A>0b)e|k^a3ZVSZ_Se){@NFv$1{$Kl z5ns_&I#Z~e@GuMtvh@LmU@ZPyw`|9Jo44X2Xx3n^tj}&THPR4luysL>ys+W+$w?>w z9xnrFD}WatJSU<^q2E}e{f~=8iH2Z(K;`*e?rHbNUD=yeB`|yWhm(2#sK3AsKP5OT zWSs}j{gWdy7w-6VCV5I*0U%NN=z-Nrq!X?WqkDfqs(|nuL7TVyTG%zXIMt7RTSo$? z-1^Q4-aTZMV0VwB_I96MiUX(qVD5jz=yw`k?~@|vbSK&on8sdykSk1yJGZ{aDChr)6GM##f3*Va$a+dZfdkW2QSekfF#GO9-^@gaENo#*V8*roEVB!o_iYZG8;rZ9|JE-BK*+Zq`kfN$*l)S909|&P5>R2OX!)<}?%8*H`XXf^2U`N; zuXujCZ`{o1o#n%38{oId`n4p{;=Dgt;+qdgcdkzI$l#;j3IN9fPFSyEwonV09;N4P605St3|Ed~l zyK8sgjDD|W?zaL!p*oI!_^=Xgf8PoRh8UHk+b^sX!)3!@O8(F`WzpYjZ)&LN7KS+# zgajsC_41`~yS!#3uI=dQv5FEPtNtP#uZ`Jy(=$EgGhMdXk-(&@UivaGx_{*xHetN0 zv=aKnnQ!c&%@V*tcR0`Dn9{j_R>SR6KOU$g2iyfP7^u6q>0!}Vb-7jNTaA30ztDuB z)uV*k8C;2k>F;VvK2FYp^o(xe1n9|I?M z9$r#^bIsib{{#6Qa2LQx+}3q8phP+jSb0{!$Se7UT0^=7F8^%NKm4^h_a3=r;ujyV z#)&CO87-`j30J*vnmT&&i@eRf#5-gZfWK-$;K$t2(jCyI{o3B{48Hfj*(#N+SpdjT z-HLrzh$X{*NBfmZnF<$=U`E9U>#^6yLd}ce1f}Di#hxjB7M|nAUJC2^eU;Y>oNxn7 z%zE6F!#GdXFqo>%-0bg7o&{|Qz`!5R^ODke_)GOmM!(!!9x`>$ngxIfOCLY~XF1gR z3Ysa!^x%2{a_@lCyTI~Lv4>_6Z|C4*)F(QckMdK<{$PZ&)Z577)AGhrpCg8i&b~Z!Pe!$ zEq{2tadp577c1nwC?|gJg;NEOe=*OC7Xmy5+{5o1I-0}Qzdr+h>1LqNECIAG)mUhc z+_rbl#=x{g>E*zPV}fh$l16 zM_=J{q5vj-@dan)S#w{6^Y_n4U5?ooLss(_Y%o&*2T-U=^m!@N_VdlRj)mz`_Vgry z30MDXlxVB`9@tP9Xfe;GN#@!GW{i1UU`EGx|yQ5tm_u_`C@I9Q66qk=0--0X%>gx{|w< z_I-1+ZTcH|&zS@-9O|ZMT)@}lw`3zdhJokucinDEL1dUrRWAYUhNO+(Opk( z{`ncr#U>hVLBKX~>S^hSq>l2&qoc6X6-KxKnFL`!^>h+x~*c}(axZYe)h$1 zU-cLOe+{^2Z>q1qay3}%Z~RQ-5!1i@(9i2{8Fpi)aWe^@V+Fu*r{26}xNF$NH#mo9 zyftnaPD8vV(D6n8m*l29qaSaB?tu+Wy$EcmTCYaKtD>Rim)^a*_M&?Oy=Xwi>}suHz!e(v%{R6@neaG8ldSzJ!@CC4ehT<#783cl+C)TN{A8 zIdk~rTmc~Ovsdgp6P5`-&#Al%PcOCfqt}w2TYjPik}LtO(xW24aRTkQ0k8_%I4Qaw z2Em?}L&w%^t-pB(w{|U6;{_w3rT3KhYDJs-EP(gf(ArNFU=M`?TdU3KVH5m@Tr}`| z3#jE!t*g0K0@xTpLvU2;Jh))ftrP#7ntryw^P&Kd>Ds#wEw=lIuCUZqOsS=jCiqQL z7n{0nAi&$#V0{);1bkq1VHg1OE+ks=*$z-o{!+g8pw2wnxHNk@PGxpEKhK0&p+ zX7MV27B2|1VL?PS-YSjTb8)+PJm0{5w|pBdKTh?5*`LJ~ekjLmJ~>kYxDtsMRKDxT z#p@T3dOVvv_eLvk3Si;Fh2q}YUq2!EhgfqwAS3V_Egt@&`P<7kDK)SRUxuX-w_NQ{&3g2f3??@VBXs>KLqf`%{%yQufneZDXptXmB|ss-x^VD-d*Gu%Sy9zyc-arCVuvCt`=vpW;AZF{ zoWM=73C=MJuTFrKdE+5=B`78@2m2tfHCGkgw8wWnFX)bsnMX{LI2mEkQ=955qyay| zbQ*v3?4=R1?;vE*uj}Y5!v5F(XZ`()@^*fCUKId}p*GMsLo6TtDlfV!v6Z0yNvhEJ z(NiVITw$9fJq92VIh{`r`NXlH}NHSBFX^nxddP$1!8jZKpU(Bu%zV< zDC7>66GAYr6oak=bScQnBtR_uC%|NrqCjN94S;q5Er%k@P8fOjLJEEuv~%M41ZW-d z1N103ct^f**M-~=IwZa`tT#W{9;`@`KFJ~ zSbx`y{e1+_s(0QM0CHb@_x^Kj-l|pb>M{p}vYM?t5z|ZG1OZfT{9mi& z0>K1@9^Rw@A#^`2PU3fB8r{S~{SK8@_8G@17@( zSg-sceW0QFYpIcRbiRm-(el^OWA^Jg>Gp%->hGfu`nAa&pPaMtwiDL%mrj4<4T=Il zW@oS5cb({|{smbjI1mZ;H|GP5r}J!r08v6JLPEtyClXGtA^N)sjMQ(FMnb&QbW*=D zA7;8Rh6Eo--%Nwh!~n>Q7FZ`i+(@_{X&P~~Uo%dRv=jIxNhGF^$rv;U1Mp3M%a7Si zd`$TyI`;8S277rvCUrGkym9eJY!LJQWOX}mCfqmNJo0{}tL2y4S%QP6hcaO~9#$`H z4P*vT&^w{xgLB*;y;4Dt@~uV3zwvmf>7;(^aWEb9$`1GmodNzKR#ql7FanI9D4k6|9W3x8yD)+?cu&pviLVJI z<0cDk|4Heb?p>BXl1eXQ~g5?xY zB!fT$OdL#**;KlHeWQRdX+2zW%Wv?ZrK2g91RxuLOihCjGzpUg^dN*kBP~5)45+6c zPcJzP31RZcVM`A+%v+6Se{q4I2#d%|d(+JRwua8;yG+qhuIDqxM#nZ!ZTJmNbWQWk~Ic_{paUM)J9PNkLTA#l-!B4~oe|S90Kh(ZS z3blL%PK3gJ90l_X>L6fGQm7A1+Ag*3{VHsa{cupP8`J81955!hbU>NR>jCjQ5me@P zVt53K5gvaNzKJt_V?+#wFUAMHY46D`KM9%?j)Y7|BN6->J)I_r3h(4o2fyKFkVQ|O zRuVs$qL~JMV1xu3Xy!xH!oUwReE@z~uDy+G?>Mi}z>lR?a25bEh0o08JEqz_BmN1N zz|_2t33RLUi9jK>J*CncKuG{Qp^@-Sz@+8P1XF4{CXn!@dph00A5XU%2niq!f1sxG zLpU(rlhVf|weVWXy~j-kKZZ`oXJVhf0$Tne81N%9?conG`(u%J!jWTNef!4YdwK{m z=uQQz08lcY3hbKbD6jc{paiDpZFV3D6k6qugG+-3e)j|@6Bs(c%x}z0D&4-mNgVAD z2F(rl6I<;B5NjF4#JlA)o+lK7!5?{nZ*72&Eb=KUZnIwle{_o!?fmM-8!Gn_VHV(@ zg6je#%4kbq;x75f$6t~o9UJnpP9PPO1PG~>ygMim2_`TIjf8I!T?2>~27%MZx0WQK z*&X~C*PwyF7}z9^2*2>29EPMCchg&XU-dZ7UF_fo zvtNydHgRnoUnykpV+j_t1%M3VgSYHBE5|$`cq=}uM8n{s*Lvccr9V9a25B3B($XHO$`i30_rV|)@AKeTW1tGjhe*9fN3#sWfmX1YnVkOm=%f5|@*E|sSKO~R0O zohO}EoL_M0C2n#UlB&)VyzAii4ujGDVh2AQ;|+t?^-@Uw>c*RWS-r#qrJn6)P?rLy zo0&sz{w_FT%7TBXp31SJ%RfEq$BGdkVBOb1qyYuFGk|Asss|)q31Jhyy90%I!XF54 z0FjWvZ}dZFd@(-oO?%hOe#4&xO$tXslAv06LdQsh(9mg;sPL|bHG}BsXq3@k3!lV~ z5myV;orYod4`VGqndgs&H^`!V-p1<+AN*LPR44#sbbrI&B9rEMo(^*-dqjtOo^~LH zR$5hwAR_{ROUPmDqS?+$*0hUSlf zOqPsvy5)s<=rkdo@u|Ob&re*N2)$-`HOU(AH{@^*5{AC1-o0%Z}^d~ zVCMNX?t1@AMHe8I{W&WST*tdAR={p5=YS3s=?0iYaA|-ccr-wajOgzscv8R3FbQBv zO(*r6#37KzKa>slLCar0l#TXB!|Rj|`TY7@=>b1hJ1P|bGG2T4o^wT4)gM6f4(->1 zp>80|BKQd@R3P}G{c6b>-{`FSV`hjmey4(8b2DgQIDAay0}kXpH81+NP8efoB(%s$ z@eL1?pCno&0wJT(&>6r!KkRzJd45+JfM4$hVCZ6dbhH00AtIf>?k4{c+VWq}vjE2v z=ElWio>g1-ehyB}-He5hkuFQB8+31mN2M zA9`rCOt6tS=&XfLp6bK!8cp(|Mb*P<5lK8fu0g{{LyM!))q`L{N%4)asd2S$gSmvX z@Rbbs@nk>A-e48L9{AwO1zl3aJo-i4WmKo0& z@T*~cetp32jjnLy!fh0q{d%n+KUPryBr|jF{CENHulg;M1~E=fc|R3i~gI$exT=#v+8O!-dmCv^002%ZdnlL|nl=fsOtN{E)b*VMvI00Rs~J?L1?J9~Q651wTCNX@02jV6A5w=r-t>qOj&1B0^HaBMm}?xRY?^w@ypCGbP3)3Xu~na%V$ zu=ar?)nms$#kohe@-};|U~{|i9s;xC0~XA81O@?0A_z3VB!|(sFx^tYmHLgr3FeT# zVfOc&t`SZrK_ZfLdZelG7Ux;x3%^a?%sd(C5k~MMAq*y?(K6$ieSTct%UXUV0xf^k zb-|YFoR(?%_1a?HE`X6i<9F85?I#IkLssw(@0SSx%-d??pa3MqfsqOdBt+csClP$d z`6h7;e*^ppX_x>7dV~%1GdR}6rKU;Zn1qq3cpM08g4m>Oq^}e17Dl6G#$#r`Q2<)Y zkKm74%j`EZ2rrf$14ztd!n-hQ`QGoqxWG>Yr*E_jSLA88)F3z#z(YWn@Qnn}jr^~L z)lg@E4?WNwe{_HHVSJ~8Ukhu{K)NKjP6HDnbW&+1_#1KKPKo>i!CvB;K-V$@$tJ{O z;MWQQ{%U>x$XdB0dSS!TlB1@F#a@a{0g&Q5_2wi(Df!{;Me5~{bJnG8;z`ygy_PCA6ggunBk&S07gmA4D6WCJ4=5m*qvv=HMyKBMZhZ+ z+*;^l1z`Xd!HE7w91Upb1}?-8Z|OxGnm{A&MmYS%xLO+8I|)o2v^dFOF}iuHFuo=# zg9O^CapUPH#xZE)=swKzvjIQS^2^c4+E_HY&}svISY1+|qE-O9FvMARe7ulzxR=5p z;dBKD3CXqP2t+M}2__w>y?$eG5=R4d@;txpsRK4KoSurNBvR8L(U2(eqy6eZ$afsr zhCe#%;q|!jFi6IrfxqyWE&q6!>Z=0p;-2aQ@UKydpyk&J-{P|XMkf3CRS&HB)qg!F zocTA0qvR0Bt0zF$po{<%z+i$&M_sSqmtHj0Nj}qQ`H`SWm?WUHL4X_w zHijbsPAC*CoKE>Sf8%53(fFX%Key4r!|0=}cqt6#a*X6LuXf{kA zYKlOW30{-Uek5i96o0kvI4=7KeiOtdZPW)yoFsrB`ZuNrkM3v2Gg^K&+ON&?7jet4 zRS;$Y7;;GaciO^$LzsB}S#WLHcR>++fw#H6Flh|R0J;b%U?jjav8lfRSV=e%7BOl7 z7=B3*{MFp_AmrNwaZlh+qJ>$B(=y|k;Aee)Z293NpI5uOB8%Q#Qr41o;ae~uvj7HA zs3+X`)=73p+1Gi|b|I`DnS$GoaV>$W$O#}s{1RjnH}akYSOf6Li1Cg}Lib^hUo)Noe%9yLTmJB?A=$O?o$L5klvFW4OaWw}^rv0D#wV6moC!+c8?cD< zEWzfiLh#|Bp{WcYojCY)fSZ6vCJZq51^(`FO`sDR8ZFaJ2fukPDf2|N^cpI?nd zUJ*LOUwgC2TYju1_%H>a$suchPrCZ0QG7}D7kR;cKF8bUz*s>kKo%?mm`>C!1I+-y zCLSK6sn>rsKh50)v8f!4mOdUg9wtu9bYla4C}HwwW`E>WTbFaun@jkjHv0{k;4f1E ziPFgO`?TxUO$2M;Y)-U)NmYe9IG3OTkJHvH11XE(N9zHZN9#aW4$SN~OOt><5_!d? zI2WyDX1^&Hd|?V8NgTQRnD*mWMys~c(_x(8^BgbE1;LN!?Jg0m0!<;HX^ucn0C7(( zzYcH{=p+pCoe+_D4%Z5xBd2znV zi=TmUgOfoQkAQUsJOW#l@z4?&NF-eb)Ct(CYsvxHO$Yow=<~Z+pC2Y@!Y_y9@YmkC zuDs|6{CcYDOab&Hl{~vmyyk@=qUxK>+r&DagRX*Lg9}jA(eUeq>(3DJFn$1C22cnJ z_UlcBfQ+)1zo+8DmLFF5y%dr|UuWR&NkW<%QvkioX3%`bUixR3%R6y2>`qbjjsFxxQFH*DfCr@sR9K#_wV zTK;Iz`8C$(@4NCc1<<#Q3O>ZNz#5;wbmrrt(|c~Ow;~mME(XpZ8SsmS|4-#yU#tHS z-#&1P)~8_EW5KOobb1a|mG@W7`Gx56G4Mwi_%p5dOaWvnu>uP}=a-#7746Q;l^7mp zR-6xM`D2k6VxiF2S<9bU9bjF6%;Z&2q37J+d6D37J_c(EV0BS(_WKF=q2)*LZ(dx% z=J_+Mp-cf}D6m2aUVDG%44d8YDimNPnE@yi#`4IA-sgW&<$}=iSF%2TKV;9k0R0f! zU`ILao+iId6n-y=w&DhVB>aLH!T~=9{{GfUrU3dYxj~GlINU#h)^8TM0(}tq7_6kR z<%dN+&#NuLZ@hI2-!WKxSRq~31)!`HXa6E}x@Z?(g;hU}V(j-5@JAxgDSX#OtmPkg z>3S$Ewy9ArM5={T%1wXX>N(%#jwkjP{0NIjc9_S1$tNJ$FWHzT57yD>t zfB1PJ)bWk_0PFK-tGcl+K(-{AV>)wx(N>|_?3)D9K8_qup5ycii9CWIZtQth40T-e z)-6L=pFfL*W6L5fMk<#Q5bfWE`w7M=QMl2#h#tJCQv&d}0Qh$>@Mpc`Sr;JdBF#R* z1^2gnh2Ven6H`TylS*8Z)=AF!4`UlooG z0_IE7{YXdVLo-A{m}K>Ne**qU=;^Mg`{MNhPgg%g#iI060?Y#Fr{MAtO%!;zgw$#2 zGD7gnkSCxl-?x%AWKHXPu`TrSnxi8-KV^6TK zO(Jsk|UolN*BiN1|Y3X=Z=qAHhiLCEISQVP^jzmK0L}gDCvtC9Md`WH{^Ja?^iC zpFieuGVmX-0_4e$DS$i)I@4r$UYLb930vvW!T*m~OY6nV>@SRxWeT7$%Ap$4`EK>k!3M!w$L@y^o7l6vL z(OUlSQ@rfHbp7?Cit7Nwd{&YyrA1{W%TnG8mJD3V;<6~1HM0#J`~d|?-lHsBX}!gwP{#nYK7Z)RG9FugX7-z9 zM&S!v30Sy=wxbXy0txuTp~ssA_jfn^h{wT7_E0PVW&spv;lXiW+h9v@L2;+G{NcYL z_;)ez7gX8wml>u2`YX8{$Kw@omnucNU|VpGQ%aA#4*tKE^RDkP@TVs;8bTFD?V>?a zdFHWoxbtJ^0_-bx*uV>eJ4}P% zhtdAWI$GS&@=s!Y{(hHeVMb&MpfJmYaHVj{8g3BB0SxfBx415A3=oA>z|vx@^+y6s z0rW>|d5dFvQ;9`FgRvk;1ApkTCVt=L4E%X3@VqC)6hPiZo_>P$EzS>Bp4%db`8^y6 z!7oLFe`(_PU(U?_^vjFJkW2v-a;XJ)h3Ax~IU#?=M8F>o{-yKSZU+8Bt{Yk6Eq^sD zOAHqsnW*wCY_`cuHvqveN5YRvZV&YNr{N$Zdn_&irT_}OfY;yPhZTX!e*~K&r<@Y- zN5hYFw0v|0T-t%V5!q7&5?~6T&Qmp`Te zvMbM=Q0t2MUQlDP_u#I;EYpXB2hr?D@VD*;@UyADEDN~c$uR{`@I}ON+iv2!I9`32 z7qh!4NN~8Y&;RF`+j9kL`6;LfIbe|~fE)-lCnP2JUzBKQPj-}m-ttF+e}wmYTF8EP$MfH@C#+-P<7Gm1EfQH~fHspMrv8EHVjXQv$WW==jXU2UKS^X);>Ymcai9 XMUkCQ=nCF$00000NkvXXu0mjf9-4As literal 0 HcmV?d00001 diff --git a/README.md b/README.md index e065190..f1f7730 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +QueryKit Logo + # QueryKit [![Build Status](http://img.shields.io/travis/QueryKit/QueryKit/master.svg?style=flat)](https://travis-ci.org/QueryKit/QueryKit) From 6a1e65752ca6177e5c4b25893d0dbe261560badc Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 1 Jun 2015 14:01:26 -0700 Subject: [PATCH 18/71] [travis] Use 6.3 "beta" --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 12dfcf2..16dee7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: objective-c +osx_image: beta-xcode6.3 before_install: - - gem install cocoapods --no-rdoc --no-ri --no-document --quiet --pre + - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet script: - set -o pipefail From a195da5015770c2327d126f530dfd8b2e0ca1682 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 1 Jun 2015 14:02:21 -0700 Subject: [PATCH 19/71] Release 0.10.0 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index d16f6f6..ec6374f 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.9.2' + spec.version = '0.10.0' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 0834669ce458ddcf90ff174a2ba6b2f495a1314d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 14 Jul 2015 10:49:16 -0700 Subject: [PATCH 20/71] Support Swift 2.0 --- QueryKit.xcodeproj/project.pbxproj | 11 ++- .../xcshareddata/xcschemes/QueryKit.xcscheme | 5 +- QueryKit/Attribute.swift | 4 +- QueryKit/Expression.swift | 16 ++-- QueryKit/Info.plist | 2 +- QueryKit/QuerySet.swift | 77 +++++++----------- QueryKitTests/AttributeTests.swift | 22 ++--- QueryKitTests/Info.plist | 2 +- QueryKitTests/PredicateTests.swift | 6 +- QueryKitTests/QueryKitTests.swift | 22 ++++- QueryKitTests/QuerySetTests.swift | 81 +++++++++---------- 11 files changed, 126 insertions(+), 122 deletions(-) diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 6fcbca1..2f85310 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -269,7 +269,8 @@ 77A9B66E1953742F0016654E /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0600; + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 0700; TargetAttributes = { 77A9B678195374490016654E = { CreatedOnToolsVersion = 6.0; @@ -375,7 +376,9 @@ 77A9B6721953742F0016654E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ENABLE_TESTABILITY = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -391,7 +394,6 @@ baseConfigurationReference = 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -433,6 +435,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; @@ -447,7 +450,6 @@ baseConfigurationReference = 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -483,6 +485,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; @@ -530,6 +533,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.10; METAL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h"; @@ -570,6 +574,7 @@ INFOPLIST_FILE = QueryKitTests/Info.plist; MACOSX_DEPLOYMENT_TARGET = 10.10; METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h"; diff --git a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme index 2fdfdb6..1aee5e5 100644 --- a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme +++ b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme @@ -1,6 +1,6 @@ + + (left: Attribute, right: AttributeT } public func << (left: Attribute, right: [AttributeType]) -> NSPredicate { - let value = map(right) { value in return value as! NSObject } + let value = right.map { value in return value as! NSObject } return left.expression << NSExpression(forConstantValue: value) } @@ -103,7 +103,7 @@ public func << (left: Attribute, right: Range NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } /// Returns an inequality predicate for the two given expressions public func != (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func > (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func >= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func < (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func <= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func ~= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LikePredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LikePredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } public func << (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.InPredicateOperatorType, options: NSComparisonPredicateOptions(0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.InPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) } diff --git a/QueryKit/Info.plist b/QueryKit/Info.plist index c8d5065..7812205 100644 --- a/QueryKit/Info.plist +++ b/QueryKit/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - org.cocode.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 5bfb3ef..8e3bf7a 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -73,7 +73,7 @@ extension QuerySet { #endif } - return QuerySet(queryset:self, sortDescriptors:map(sortDescriptors, reverseSortDescriptor), predicate:predicate, range:range) + return QuerySet(queryset:self, sortDescriptors:sortDescriptors.map(reverseSortDescriptor), predicate:predicate, range:range) } // MARK: Filtering @@ -114,14 +114,16 @@ extension QuerySet { public subscript(index: Int) -> (object:ModelType?, error:NSError?) { get { - var request = fetchRequest + let request = fetchRequest request.fetchOffset = index request.fetchLimit = 1 var error:NSError? - if let items = context.executeFetchRequest(request, error:&error) { + do { + let items = try context.executeFetchRequest(request) return (object:items.first as? ModelType, error:error) - } else { + } catch let error1 as NSError { + error = error1 return (object: nil, error: error) } } @@ -163,7 +165,7 @@ extension QuerySet { // MARK: Conversion public var fetchRequest:NSFetchRequest { - var request = NSFetchRequest(entityName:entityName) + let request = NSFetchRequest(entityName:entityName) request.predicate = predicate request.sortDescriptors = sortDescriptors @@ -175,32 +177,23 @@ extension QuerySet { return request } - public func array() -> (objects:([ModelType]?), error:NSError?) { - var error:NSError? - var objects = context.executeFetchRequest(fetchRequest, error:&error) as? [ModelType] - return (objects:objects, error:error) - } - - public func array() -> [ModelType]? { - return array().objects + public func array() throws -> [ModelType] { + let objects = try context.executeFetchRequest(fetchRequest) as! [ModelType] + return objects } // MARK: Count - public func count() -> (count:Int?, error:NSError?) { + /// Returns the count of objects matching the QuerySet. + public func count() throws -> Int { var error:NSError? - var count:Int? = context.countForFetchRequest(fetchRequest, error: &error) + let count:Int? = context.countForFetchRequest(fetchRequest, error: &error) - if count! == NSNotFound { - count = nil + if let error = error { + throw error } - return (count:count, error:error) - } - - /// Returns the count of objects matching the QuerySet. - public func count() -> Int? { - return count().count + return count as Int! } // MARK: Exists @@ -208,44 +201,34 @@ extension QuerySet { /** Returns true if the QuerySet contains any results, and false if not. :note: Returns nil if the operation could not be completed. */ - public func exists() -> Bool? { - let result:Int? = count() - - if let result = result { - return result > 0 - } - - return nil + public func exists() throws -> Bool { + let result:Int = try count() + return result > 0 } // MARK: Deletion /// Deletes all the objects matching the QuerySet. - public func delete() -> (count:Int, error:NSError?) { - var result = array() as (objects:([ModelType]?), error:NSError?) - var deletedCount = 0 + public func delete() throws -> Int { + let objects = try array() + let deletedCount = objects.count - if let objects = result.objects { - for object in objects { - context.deleteObject(object) - } - - deletedCount = objects.count + for object in objects { + context.deleteObject(object) } - return (count:deletedCount, error:result.error) + return deletedCount } // MARK: Sequence public func generate() -> IndexingGenerator> { - var result = self.array() as (objects:([ModelType]?), error:NSError?) - - if let objects = result.objects { - return objects.generate() + do { + let generator = try self.array().generate() + return generator + } catch { + return [].generate() } - - return [].generate() } } diff --git a/QueryKitTests/AttributeTests.swift b/QueryKitTests/AttributeTests.swift index d1edbcc..642e3ef 100644 --- a/QueryKitTests/AttributeTests.swift +++ b/QueryKitTests/AttributeTests.swift @@ -50,59 +50,59 @@ class AttributeTests: XCTestCase { // Operators func testEqualityOperator() { - var predicate:NSPredicate = (attribute == 10) + let predicate:NSPredicate = (attribute == 10) XCTAssertEqual(predicate, NSPredicate(format:"age == 10")) } func testInequalityOperator() { - var predicate:NSPredicate = (attribute != 10) + let predicate:NSPredicate = (attribute != 10) XCTAssertEqual(predicate, NSPredicate(format:"age != 10")) } func testGreaterThanOperator() { - var predicate:NSPredicate = (attribute > 10) + let predicate:NSPredicate = (attribute > 10) XCTAssertEqual(predicate, NSPredicate(format:"age > 10")) } func testGreaterOrEqualThanOperator() { - var predicate:NSPredicate = (attribute >= 10) + let predicate:NSPredicate = (attribute >= 10) XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")) } func testLessThanOperator() { - var predicate:NSPredicate = (attribute < 10) + let predicate:NSPredicate = (attribute < 10) XCTAssertEqual(predicate, NSPredicate(format:"age < 10")) } func testLessOrEqualThanOperator() { - var predicate:NSPredicate = (attribute <= 10) + let predicate:NSPredicate = (attribute <= 10) XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")) } func testLikeOperator() { - var predicate:NSPredicate = (attribute ~= 10) + let predicate:NSPredicate = (attribute ~= 10) XCTAssertEqual(predicate, NSPredicate(format:"age LIKE 10")) } func testInOperator() { - var predicate:NSPredicate = (attribute << [5, 10]) + let predicate:NSPredicate = (attribute << [5, 10]) XCTAssertEqual(predicate, NSPredicate(format:"age IN %@", [5, 10])) } func testBetweenRangeOperator() { - var predicate:NSPredicate = attribute << (5..<10) + let predicate:NSPredicate = attribute << (5..<10) XCTAssertEqual(predicate, NSPredicate(format:"age BETWEEN %@", [5, 10])) } func testOptionalEqualityOperator() { let attribute = Attribute("name") - var predicate:NSPredicate = (attribute == "kyle") + let predicate:NSPredicate = (attribute == "kyle") XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")) } func testOptionalNSObjectEqualityOperator() { let attribute = Attribute("name") - var predicate:NSPredicate = (attribute == "kyle") + let predicate:NSPredicate = (attribute == "kyle") XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")) } } diff --git a/QueryKitTests/Info.plist b/QueryKitTests/Info.plist index 205ebc1..6d32c15 100644 --- a/QueryKitTests/Info.plist +++ b/QueryKitTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - org.cocode.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/QueryKitTests/PredicateTests.swift b/QueryKitTests/PredicateTests.swift index 200c285..901a094 100644 --- a/QueryKitTests/PredicateTests.swift +++ b/QueryKitTests/PredicateTests.swift @@ -14,17 +14,17 @@ class PredicateTests: XCTestCase { var agePredicate = NSPredicate(format: "age >= 21") func testAndPredicate() { - var predicate = namePredicate && agePredicate + let predicate = namePredicate && agePredicate XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle AND age >= 21")) } func testOrPredicate() { - var predicate = namePredicate || agePredicate + let predicate = namePredicate || agePredicate XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle OR age >= 21")) } func testNotPredicate() { - var predicate = !namePredicate + let predicate = !namePredicate XCTAssertEqual(predicate, NSPredicate(format: "NOT name == Kyle")) } } diff --git a/QueryKitTests/QueryKitTests.swift b/QueryKitTests/QueryKitTests.swift index cfedf7b..60410e4 100644 --- a/QueryKitTests/QueryKitTests.swift +++ b/QueryKitTests/QueryKitTests.swift @@ -44,6 +44,26 @@ func managedObjectModel() -> NSManagedObjectModel { func persistentStoreCoordinator() -> NSPersistentStoreCoordinator { let model = managedObjectModel() let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model) - persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil, error: nil) + do { + try persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil) + } catch _ { + } return persistentStoreCoordinator } + +public func AssertNotThrow(@autoclosure closure: () throws -> R) -> R? { + var result: R? + AssertNotThrow() { + result = try closure() + } + return result +} + +public func AssertNotThrow(@noescape closure: () throws -> ()) { + do { + try closure() + } catch let error { + XCTFail("Catched error \(error), " + + "but did not expect any error.") + } +} diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 60f9e43..5ade78d 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -25,7 +25,10 @@ class QuerySetTests: XCTestCase { person.name = name } - context.save(nil) + do { + try context.save() + } catch _ { + } queryset = QuerySet(context, "Person") } @@ -38,13 +41,13 @@ class QuerySetTests: XCTestCase { func testOrderBySortDescriptor() { let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - var qs = queryset.orderBy(sortDescriptor) + let qs = queryset.orderBy(sortDescriptor) XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) } func testOrderBySortDescriptors() { let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - var qs = queryset.orderBy([sortDescriptor]) + let qs = queryset.orderBy([sortDescriptor]) XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) } @@ -63,7 +66,7 @@ class QuerySetTests: XCTestCase { func testFilterPredicate() { let predicate = NSPredicate(format: "name == Kyle") - var qs = queryset.filter(predicate) + let qs = queryset.filter(predicate) XCTAssertEqual(qs.predicate!, predicate) } @@ -71,7 +74,7 @@ class QuerySetTests: XCTestCase { let predicateName = NSPredicate(format: "name == Kyle") let predicateAge = NSPredicate(format: "age > 27") - var qs = queryset.filter([predicateName, predicateAge]) + let qs = queryset.filter([predicateName, predicateAge]) XCTAssertEqual(qs.predicate!, NSPredicate(format: "name == Kyle AND age > 27")) } @@ -84,7 +87,7 @@ class QuerySetTests: XCTestCase { func testExcludePredicate() { let predicate = NSPredicate(format: "name == Kyle") - var qs = queryset.exclude(predicate) + let qs = queryset.exclude(predicate) XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT name == Kyle")) } @@ -92,7 +95,7 @@ class QuerySetTests: XCTestCase { let predicateName = NSPredicate(format: "name == Kyle") let predicateAge = NSPredicate(format: "age > 27") - var qs = queryset.exclude([predicateName, predicateAge]) + let qs = queryset.exclude([predicateName, predicateAge]) XCTAssertEqual(qs.predicate!, NSPredicate(format: "NOT (name == Kyle AND age > 27)")) } @@ -120,13 +123,13 @@ class QuerySetTests: XCTestCase { // MARK: Subscripting func testSubscriptingAtIndex() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - var ayaka = qs[0].object - var kyle = qs[1].object - var mark = qs[2].object - var orta:Person? = qs[3].object - var scott:Person? = qs[4] + let ayaka = qs[0].object + let kyle = qs[1].object + let mark = qs[2].object + let orta:Person? = qs[3].object + let scott:Person? = qs[4] XCTAssertEqual(ayaka!.name, "Ayaka") XCTAssertEqual(kyle!.name, "Kyle") @@ -136,7 +139,7 @@ class QuerySetTests: XCTestCase { } func testSubscriptingRange() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...2] + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...2] XCTAssertEqual(qs.range!.startIndex, 0) XCTAssertEqual(qs.range!.endIndex, 3) @@ -154,75 +157,65 @@ class QuerySetTests: XCTestCase { // MARK: Getters func testFirst() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) XCTAssertEqual(qs.first!.name, "Ayaka") } func testLast() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) XCTAssertEqual(qs.last!.name, "Scott") } // MARK: Conversion func testConversionToArray() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var people = qs.array().objects + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + let people = AssertNotThrow(try qs.array()) ?? [] - XCTAssertEqual(people!.count, 2) - } - - func testConversionToArrayWithoutError() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var people = qs.array() as [Person]? - - XCTAssertEqual(people!.count, 2) + XCTAssertEqual(people.count, 2) } // MARK: Count func testCount() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var count = qs.count().count - - XCTAssertEqual(count!, 2) - } - - func testCountWithoutError() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] - var count = qs.count() as Int? + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true))[0...1] + let count = AssertNotThrow(try qs.count()) XCTAssertEqual(count!, 2) } // MARK: Exists - func testExistsReturnsTrueWithMatchingObjects() { + func testExistsReturnsTrueWithMatchingObjects() { let qs = queryset.filter(NSPredicate(format: "name == %@", "Kyle")) - XCTAssertTrue(qs.exists()!) + let exists = AssertNotThrow(try qs.exists()) ?? false + + XCTAssertTrue(exists) } - func testExistsReturnsFalseWithNoMatchingObjects() { + func testExistsReturnsFalseWithNoMatchingObjects() { let qs = queryset.filter(NSPredicate(format: "name == %@", "None")) - XCTAssertFalse(qs.exists()!) + let exists = AssertNotThrow(try qs.exists()) ?? true + + XCTAssertFalse(exists) } // MARK: Deletion func testDelete() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - var deletedCount = qs[0...1].delete().count - var count = qs.count() as Int? + let deletedCount = AssertNotThrow(try qs[0...1].delete()) ?? 0 + let count = AssertNotThrow(try qs.count()) ?? 0 XCTAssertEqual(deletedCount, 2) - XCTAssertEqual(count!, 3) + XCTAssertEqual(count, 3) } // MARK: Sequence func testSequence() { - var qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) + let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) var objects = [Person]() for object in qs { From cb38b49ed379039da56e6a6173b308cbcffa7419 Mon Sep 17 00:00:00 2001 From: Dirk Fabisch Date: Tue, 25 Aug 2015 21:15:29 +0200 Subject: [PATCH 21/71] Fix Join unavailable Swift Beta 6 'join' is unavailable: call the 'joinWithSeparator()' method on the sequence of elements --- QueryKit/Attribute.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index 51aa803..d453a19 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -18,7 +18,7 @@ public struct Attribute : Equatable { /// Builds a compound attribute with other key paths public init(attributes:Array) { - self.init(".".join(attributes)) + self.init(attributes.joinWithSeparator(".")) } /// Returns an expression for the attribute From 17120ec9479492a46457915a5dc0cfbb461e4ec3 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 5 Sep 2015 22:26:34 -0700 Subject: [PATCH 22/71] Remove OS X workaround due to AppKit bug in CocoaPods --- QueryKit/QuerySet.swift | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 8e3bf7a..a228177 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -9,11 +9,6 @@ import Foundation import CoreData -#if os(OSX) && COCOAPODS - import AppKit -#endif - - /// Represents a lazy database lookup for a set of objects. public class QuerySet : SequenceType, Equatable { /// Returns the managed object context that will be used to execute any requests. @@ -66,11 +61,7 @@ extension QuerySet { /// Reverses the ordering of the QuerySet public func reverse() -> QuerySet { func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { - #if os(OSX) && COCOAPODS - return NSSortDescriptor(key: sortDescriptor.key()!, ascending: !sortDescriptor.ascending) - #else - return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) - #endif + return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) } return QuerySet(queryset:self, sortDescriptors:sortDescriptors.map(reverseSortDescriptor), predicate:predicate, range:range) From ea0be394e6610c612e73b53dc2b949a2bfb6f0b9 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 6 Sep 2015 13:34:23 -0700 Subject: [PATCH 23/71] Expose errors from all queryset operations --- QueryKit/QuerySet.swift | 45 +++++++++++-------------------- QueryKitTests/QuerySetTests.swift | 23 ++++++++-------- README.md | 22 +++++++-------- 3 files changed, 38 insertions(+), 52 deletions(-) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index a228177..4b53593 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -23,6 +23,7 @@ public class QuerySet : SequenceType, Equatable { /// Returns the predicate of the receiver. public let predicate:NSPredicate? + /// The range of the query, allows you to offset and limit a query public let range:Range? // MARK: Initialization @@ -35,6 +36,7 @@ public class QuerySet : SequenceType, Equatable { self.range = nil } + /// Create a queryset from another queryset with a different sortdescriptor predicate and range public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { self.context = queryset.context self.entityName = queryset.entityName @@ -103,28 +105,13 @@ extension QuerySet { extension QuerySet { // MARK: Subscripting - public subscript(index: Int) -> (object:ModelType?, error:NSError?) { - get { - let request = fetchRequest - request.fetchOffset = index - request.fetchLimit = 1 - - var error:NSError? - do { - let items = try context.executeFetchRequest(request) - return (object:items.first as? ModelType, error:error) - } catch let error1 as NSError { - error = error1 - return (object: nil, error: error) - } - } - } - /// Returns the object at the specified index. - public subscript(index: Int) -> ModelType? { - get { - return self[index].object - } + public func object(index: Int) throws -> ModelType? { + let request = fetchRequest + request.fetchOffset = index + request.fetchLimit = 1 + let items = try context.executeFetchRequest(request) + return items.first as? ModelType } public subscript(range:Range) -> QuerySet { @@ -141,20 +128,19 @@ extension QuerySet { // Mark: Getters - public var first: ModelType? { - get { - return self[0].object - } + /// Returns the first object in the QuerySet + public func first() throws -> ModelType? { + return try self.object(0) } - public var last: ModelType? { - get { - return reverse().first - } + /// Returns the last object in the QuerySet + public func last() throws -> ModelType? { + return try reverse().first() } // MARK: Conversion + /// Returns a fetch request equivilent to the QuerySet public var fetchRequest:NSFetchRequest { let request = NSFetchRequest(entityName:entityName) request.predicate = predicate @@ -168,6 +154,7 @@ extension QuerySet { return request } + /// Returns an array of all objects matching the QuerySet public func array() throws -> [ModelType] { let objects = try context.executeFetchRequest(fetchRequest) as! [ModelType] return objects diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 5ade78d..17ea233 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -25,10 +25,7 @@ class QuerySetTests: XCTestCase { person.name = name } - do { - try context.save() - } catch _ { - } + try! context.save() queryset = QuerySet(context, "Person") } @@ -59,7 +56,7 @@ class QuerySetTests: XCTestCase { XCTAssertEqual(qs.sortDescriptors, [ NSSortDescriptor(key: "name", ascending: false), NSSortDescriptor(key: "age", ascending: false), - ]) + ]) } // MARK: Filtering @@ -125,11 +122,11 @@ class QuerySetTests: XCTestCase { func testSubscriptingAtIndex() { let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - let ayaka = qs[0].object - let kyle = qs[1].object - let mark = qs[2].object - let orta:Person? = qs[3].object - let scott:Person? = qs[4] + let ayaka = try! qs.object(0) + let kyle = try! qs.object(1) + let mark = try! qs.object(2) + let orta = try! qs.object(3) + let scott = try! qs.object(4) XCTAssertEqual(ayaka!.name, "Ayaka") XCTAssertEqual(kyle!.name, "Kyle") @@ -158,12 +155,14 @@ class QuerySetTests: XCTestCase { func testFirst() { let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - XCTAssertEqual(qs.first!.name, "Ayaka") + let name = try! qs.first()?.name + XCTAssertEqual(name, "Ayaka") } func testLast() { let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - XCTAssertEqual(qs.last!.name, "Scott") + let name = try! qs.last()?.name + XCTAssertEqual(name, "Scott") } // MARK: Conversion diff --git a/README.md b/README.md index f1f7730..bd8eeb1 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,6 @@ QueryKit, a simple type-safe Core Data query language. -## Installation - -```ruby -pod 'QueryKit' -``` - ## Usage ### QuerySet @@ -21,13 +15,13 @@ A QuerySet represents a collection of objects from your Core Data Store. It can #### Retrieving all objects ```swift -QuerySet(context, "Person") +let queryset = QuerySet(context, "Person") ``` **NOTE**: *It’s recommend to implement a type type-safe `queryset` method on your model.* ```swift -Person.queryset(context) +let queryset = Person.queryset(context) ``` #### Retrieving specific objects with filters @@ -114,19 +108,19 @@ queryset.array() ##### First object ```swift -var kyle = Person.queryset(context).filter(Person.name == "Kyle").first +var kyle = Person.queryset(context).filter(Person.name == "Kyle").first() ``` ##### Last object ```swift -var kyle = Person.queryset(context).filter(Person.name == "Kyle").last +var kyle = Person.queryset(context).filter(Person.name == "Kyle").last() ``` ##### Object at index ```swift -var orta = queryset[3] +var orta = queryset.object(3) ``` ##### Count @@ -191,6 +185,12 @@ Person.name == "Kyle" || Person.name == "Katie" Person.age >= 21 || Person.name != "Kyle" ``` +## Installation + +```ruby +pod 'QueryKit' +``` + ## License QueryKit is released under the BSD license. See [LICENSE](LICENSE). From 0e6aa4fae4179a1796b887f59733644e6a6ee6b9 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 6 Sep 2015 16:19:14 -0700 Subject: [PATCH 24/71] Require iOS 8 and OS X 10.9 --- QueryKit.podspec | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index ec6374f..88d4677 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -9,8 +9,8 @@ Pod::Spec.new do |spec| spec.source = { :git => 'https://github.com/QueryKit/QueryKit.git', :tag => "#{spec.version}" } spec.source_files = 'QueryKit/QueryKit.h' spec.requires_arc = true - spec.ios.deployment_target = '5.0' - spec.osx.deployment_target = '10.7' + spec.ios.deployment_target = '8.0' + spec.osx.deployment_target = '10.9' spec.subspec 'ObjectiveC' do |objc_spec| objc_spec.dependency 'QueryKit/Attribute/ObjectiveC' @@ -20,9 +20,6 @@ Pod::Spec.new do |spec| spec.subspec 'Swift' do |swift_spec| swift_spec.dependency 'QueryKit/Attribute/Swift' swift_spec.dependency 'QueryKit/QuerySet/Swift' - - swift_spec.ios.deployment_target = '8.0' - swift_spec.osx.deployment_target = '10.9' end spec.subspec 'Attribute' do |attribute_spec| @@ -33,18 +30,12 @@ Pod::Spec.new do |spec| attribute_spec.subspec 'Swift' do |swift_spec| swift_spec.dependency 'QueryKit/QuerySet/Swift' swift_spec.source_files = 'QueryKit/{Attribute,Expression,Predicate}.swift' - - swift_spec.ios.deployment_target = '8.0' - swift_spec.osx.deployment_target = '10.9' end attribute_spec.subspec 'Bridge' do |bridge_spec| bridge_spec.dependency 'QueryKit/Attribute/Swift' bridge_spec.dependency 'QueryKit/Attribute/ObjectiveC' bridge_spec.source_files = 'QueryKit/ObjectiveC/QKAttribute.swift' - - bridge_spec.ios.deployment_target = '8.0' - bridge_spec.osx.deployment_target = '10.9' end end @@ -55,18 +46,12 @@ Pod::Spec.new do |spec| queryset_spec.subspec 'Swift' do |swift_spec| swift_spec.source_files = 'QueryKit/QuerySet.swift' - - swift_spec.ios.deployment_target = '8.0' - swift_spec.osx.deployment_target = '10.9' end queryset_spec.subspec 'Bridge' do |bridge_spec| bridge_spec.dependency 'QueryKit/QuerySet/Swift' bridge_spec.dependency 'QueryKit/QuerySet/ObjectiveC' bridge_spec.source_files = 'QueryKit/ObjectiveC/QKQuerySet.swift' - - bridge_spec.ios.deployment_target = '8.0' - bridge_spec.osx.deployment_target = '10.9' end end end From 6552df8f9e6c7465be9259c8ddfd6b4839a614ff Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 6 Sep 2015 16:12:20 -0700 Subject: [PATCH 25/71] Release 0.11.0-beta.1 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 88d4677..fa7d5d6 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.10.0' + spec.version = '0.11.0-beta.1' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 203d0da0993c335391a1bfc53b7d07a70bf70847 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 15:41:36 -0700 Subject: [PATCH 26/71] [travis] Use Xcode 7 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 16dee7b..db99e1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: beta-xcode6.3 +osx_image: xcode7 before_install: - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet From 4d4a97b568ec8b1c52050a7cba787f5e15b071a3 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 15:25:47 -0700 Subject: [PATCH 27/71] Introduce type safe predicates --- QueryKit.xcodeproj/project.pbxproj | 2 +- QueryKit/Predicate.swift | 62 ++++++++++++++ QueryKit/QuerySet.swift | 22 +++++ QueryKitTests/AttributeTests.swift | 1 - QueryKitTests/PredicateTests.swift | 126 ++++++++++++++++++++++++----- QueryKitTests/QueryKitTests.swift | 4 + QueryKitTests/QuerySetTests.swift | 13 +++ 7 files changed, 210 insertions(+), 20 deletions(-) diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 2f85310..131e6a4 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -169,6 +169,7 @@ 77E3A05E1969C047009372A8 /* QuerySetTests.swift */, 77E3A0621969E003009372A8 /* ExpressionTests.swift */, 77E8728219539C2A00A6F13F /* AttributeTests.swift */, + 77E8728419539FC000A6F13F /* PredicateTests.swift */, 77B17B8919A94D4C00D6540D /* ObjectiveC */, 77A9B689195374490016654E /* Supporting Files */, ); @@ -178,7 +179,6 @@ 77A9B689195374490016654E /* Supporting Files */ = { isa = PBXGroup; children = ( - 77E8728419539FC000A6F13F /* PredicateTests.swift */, 77A9B68A195374490016654E /* Info.plist */, ); name = "Supporting Files"; diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index 170de98..9ec4db6 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -22,3 +22,65 @@ public func || (left: NSPredicate, right: NSPredicate) -> NSPredicate { prefix public func ! (left: NSPredicate) -> NSPredicate { return NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [left]) } + +// MARK: Predicate Type + +/// Represents a predicate for a specific model +public struct Predicate { + let predicate:NSPredicate + + init(predicate:NSPredicate) { + self.predicate = predicate + } +} + +public func == (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left == right) +} + +public func != (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left != right) +} + +public func > (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left > right) +} + +public func >= (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left >= right) +} + +public func < (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left < right) +} + +public func <= (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left <= right) +} + +public func ~= (left: Attribute, right: AttributeType) -> Predicate { + return Predicate(predicate: left ~= right) +} + +public func << (left: Attribute, right: [AttributeType]) -> Predicate { + return Predicate(predicate: left << right) +} + +public func << (left: Attribute, right: Range) -> Predicate { + return Predicate(predicate: left << right) +} + +/// Returns an and predicate from the given predicates +public func && (left: Predicate, right: Predicate) -> Predicate { + return Predicate(predicate: left.predicate && right.predicate) +} + +/// Returns an or predicate from the given predicates +public func || (left: Predicate, right: Predicate) -> Predicate { + return Predicate(predicate: left.predicate || right.predicate) +} + +/// Returns a predicate reversing the given predicate +prefix public func ! (predicate: Predicate) -> Predicate { + return Predicate(predicate: !predicate.predicate) +} diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 4b53593..f568859 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -99,6 +99,28 @@ extension QuerySet { let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) return exclude(excludePredicate) } + + // MARK: Type-safe filtering + + /// Returns a new QuerySet containing objects that match the given predicate. + public func filter(closure:((ModelType.Type) -> (Predicate))) -> QuerySet { + return filter(closure(ModelType.self).predicate) + } + + /// Returns a new QuerySet containing objects that exclude the given predicate. + public func exclude(closure:((ModelType.Type) -> (Predicate))) -> QuerySet { + return exclude(closure(ModelType.self).predicate) + } + + /// Returns a new QuerySet containing objects that match the given predicatess. + public func filter(closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { + return filter(closures.map { $0(ModelType.self).predicate }) + } + + /// Returns a new QuerySet containing objects that exclude the given predicates. + public func exclude(closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { + return exclude(closures.map { $0(ModelType.self).predicate }) + } } /// Functions for evauluating a QuerySet diff --git a/QueryKitTests/AttributeTests.swift b/QueryKitTests/AttributeTests.swift index 642e3ef..90ff93f 100644 --- a/QueryKitTests/AttributeTests.swift +++ b/QueryKitTests/AttributeTests.swift @@ -14,7 +14,6 @@ class AttributeTests: XCTestCase { override func setUp() { super.setUp() - attribute = Attribute("age") } diff --git a/QueryKitTests/PredicateTests.swift b/QueryKitTests/PredicateTests.swift index 901a094..a87f66f 100644 --- a/QueryKitTests/PredicateTests.swift +++ b/QueryKitTests/PredicateTests.swift @@ -7,24 +7,114 @@ // import XCTest -import QueryKit +@testable import QueryKit + + +class NSPredicateTests: XCTestCase { + var namePredicate = NSPredicate(format: "name == Kyle") + var agePredicate = NSPredicate(format: "age >= 21") + + func testAndPredicate() { + let predicate = namePredicate && agePredicate + XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle AND age >= 21")) + } + + func testOrPredicate() { + let predicate = namePredicate || agePredicate + XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle OR age >= 21")) + } + + func testNotPredicate() { + let predicate = !namePredicate + XCTAssertEqual(predicate, NSPredicate(format: "NOT name == Kyle")) + } +} + class PredicateTests: XCTestCase { - var namePredicate = NSPredicate(format: "name == Kyle") - var agePredicate = NSPredicate(format: "age >= 21") - - func testAndPredicate() { - let predicate = namePredicate && agePredicate - XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle AND age >= 21")) - } - - func testOrPredicate() { - let predicate = namePredicate || agePredicate - XCTAssertEqual(predicate, NSPredicate(format: "name == Kyle OR age >= 21")) - } - - func testNotPredicate() { - let predicate = !namePredicate - XCTAssertEqual(predicate, NSPredicate(format: "NOT name == Kyle")) - } + var attribute:Attribute! + + override func setUp() { + super.setUp() + attribute = Attribute("age") + } + + // MARK: Operators + + func testEqualityOperator() { + let predicate:Predicate = attribute == 10 + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age == 10")) + } + + func testInequalityOperator() { + let predicate:Predicate = (attribute != 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age != 10")) + } + + func testGreaterThanOperator() { + let predicate:Predicate = (attribute > 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age > 10")) + } + + func testGreaterOrEqualThanOperator() { + let predicate:Predicate = (attribute >= 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age >= 10")) + } + + func testLessThanOperator() { + let predicate:Predicate = (attribute < 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age < 10")) + } + + func testLessOrEqualThanOperator() { + let predicate:Predicate = (attribute <= 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age <= 10")) + } + + func testLikeOperator() { + let predicate:Predicate = (attribute ~= 10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age LIKE 10")) + } + + func testInOperator() { + let predicate:Predicate = (attribute << [5, 10]) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age IN %@", [5, 10])) + } + + func testBetweenRangeOperator() { + let predicate:Predicate = attribute << (5..<10) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age BETWEEN %@", [5, 10])) + } + + func testOptionalEqualityOperator() { + let attribute = Attribute("name") + let predicate:Predicate = (attribute == "kyle") + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == 'kyle'")) + } + + func testOptionalNSObjectEqualityOperator() { + let attribute = Attribute("name") + let predicate:Predicate = (attribute == "kyle") + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == 'kyle'")) + } + + // MARK: + + var namePredicate = Predicate(predicate: NSPredicate(format: "name == Kyle")) + var agePredicate = Predicate(predicate: NSPredicate(format: "age >= 21")) + + func testAndPredicate() { + let predicate = namePredicate && agePredicate + XCTAssertEqual(predicate.predicate, NSPredicate(format: "name == Kyle AND age >= 21")) + } + + func testOrPredicate() { + let predicate = namePredicate || agePredicate + XCTAssertEqual(predicate.predicate, NSPredicate(format: "name == Kyle OR age >= 21")) + } + + func testNotPredicate() { + let predicate = !namePredicate + XCTAssertEqual(predicate.predicate, NSPredicate(format: "NOT name == Kyle")) + } } diff --git a/QueryKitTests/QueryKitTests.swift b/QueryKitTests/QueryKitTests.swift index 60410e4..38ba892 100644 --- a/QueryKitTests/QueryKitTests.swift +++ b/QueryKitTests/QueryKitTests.swift @@ -16,6 +16,10 @@ import CoreData class var entityName:String { return "Person" } + + class var name:Attribute { + return Attribute("name") + } } extension Person { diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 17ea233..0e70856 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -10,6 +10,7 @@ import XCTest import CoreData import QueryKit + class QuerySetTests: XCTestCase { var context:NSManagedObjectContext! var queryset:QuerySet! @@ -80,6 +81,12 @@ class QuerySetTests: XCTestCase { XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == YES")) } + func testTypeSafeFilter() { + let qs = queryset.filter { $0.name == "Kyle" } + + XCTAssertEqual(qs.predicate?.description, "name == \"Kyle\"") + } + // MARK: Exclusion func testExcludePredicate() { @@ -101,6 +108,12 @@ class QuerySetTests: XCTestCase { XCTAssertEqual(qs.predicate!, NSPredicate(format: "isEmployed == NO")) } + func testTypeSafeExclude() { + let qs = queryset.exclude { $0.name == "Kyle" } + + XCTAssertEqual(qs.predicate?.description, "NOT name == \"Kyle\"") + } + // Fetch Request func testConversionToFetchRequest() { From 5f67813a6fc012038ca922f957b9abd1b6ce029e Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 15:39:42 -0700 Subject: [PATCH 28/71] Introduce type safe sort descriptors --- QueryKit.xcodeproj/project.pbxproj | 8 ++++++++ QueryKit/QuerySet.swift | 12 ++++++++++++ QueryKit/SortDescriptor.swift | 22 ++++++++++++++++++++++ QueryKitTests/QuerySetTests.swift | 11 +++++++++++ QueryKitTests/SortDescriptorTests.swift | 21 +++++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 QueryKit/SortDescriptor.swift create mode 100644 QueryKitTests/SortDescriptorTests.swift diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 131e6a4..e769bea 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 2794C8AD1B9F980100216C36 /* SortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */; settings = {ASSET_TAGS = (); }; }; + 2794C8AF1B9F985900216C36 /* SortDescriptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */; settings = {ASSET_TAGS = (); }; }; 77007D7D19A95CDE007DC2BC /* QKQuerySetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77007D7C19A95CDE007DC2BC /* QKQuerySetTests.swift */; }; 77007D8119A95CE9007DC2BC /* QKQuerySet.h in Headers */ = {isa = PBXBuildFile; fileRef = 77007D7E19A95CE9007DC2BC /* QKQuerySet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 77007D8219A95CE9007DC2BC /* QKQuerySet.m in Sources */ = {isa = PBXBuildFile; fileRef = 77007D7F19A95CE9007DC2BC /* QKQuerySet.m */; }; @@ -64,6 +66,8 @@ 279294E51A4B4C60009C52E1 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; + 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptor.swift; sourceTree = ""; }; + 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptorTests.swift; sourceTree = ""; }; 77007D7C19A95CDE007DC2BC /* QKQuerySetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKQuerySetTests.swift; sourceTree = ""; }; 77007D7E19A95CE9007DC2BC /* QKQuerySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QKQuerySet.h; sourceTree = ""; }; 77007D7F19A95CE9007DC2BC /* QKQuerySet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKQuerySet.m; sourceTree = ""; }; @@ -148,6 +152,7 @@ 77E8728019539C0900A6F13F /* Attribute.swift */, 77E3A0601969DDF5009372A8 /* Expression.swift */, 77E8728619539FD200A6F13F /* Predicate.swift */, + 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */, 77B17B8219A94C9100D6540D /* ObjectiveC */, 77A9B67C195374490016654E /* Supporting Files */, ); @@ -170,6 +175,7 @@ 77E3A0621969E003009372A8 /* ExpressionTests.swift */, 77E8728219539C2A00A6F13F /* AttributeTests.swift */, 77E8728419539FC000A6F13F /* PredicateTests.swift */, + 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */, 77B17B8919A94D4C00D6540D /* ObjectiveC */, 77A9B689195374490016654E /* Supporting Files */, ); @@ -326,6 +332,7 @@ 77B17B8619A94C9100D6540D /* QKAttribute.m in Sources */, 77B17B8819A94D2C00D6540D /* QKAttribute.swift in Sources */, 77007D8319A95CE9007DC2BC /* QKQuerySet.swift in Sources */, + 2794C8AD1B9F980100216C36 /* SortDescriptor.swift in Sources */, 77007D8219A95CE9007DC2BC /* QKQuerySet.m in Sources */, 77E3A05D1969C019009372A8 /* QuerySet.swift in Sources */, 77E3A0611969DDF5009372A8 /* Expression.swift in Sources */, @@ -338,6 +345,7 @@ files = ( 77B17B8B19A94D4C00D6540D /* QKAttributeTests.swift in Sources */, 77E8728319539C2A00A6F13F /* AttributeTests.swift in Sources */, + 2794C8AF1B9F985900216C36 /* SortDescriptorTests.swift in Sources */, 77A9B68C195374490016654E /* QueryKitTests.swift in Sources */, 77007D7D19A95CDE007DC2BC /* QKQuerySetTests.swift in Sources */, 77E3A05F1969C047009372A8 /* QuerySetTests.swift in Sources */, diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index f568859..f5ad459 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -69,6 +69,18 @@ extension QuerySet { return QuerySet(queryset:self, sortDescriptors:sortDescriptors.map(reverseSortDescriptor), predicate:predicate, range:range) } + // MARK: Type-safe Sorting + + /// Returns a new QuerySet containing objects ordered by the given sort descriptor. + public func orderBy(closure:((ModelType.Type) -> (SortDescriptor))) -> QuerySet { + return orderBy(closure(ModelType.self).sortDescriptor) + } + + /// Returns a new QuerySet containing objects ordered by the given sort descriptors. + public func orderBy(closure:((ModelType.Type) -> ([SortDescriptor]))) -> QuerySet { + return orderBy(closure(ModelType.self).map { $0.sortDescriptor }) + } + // MARK: Filtering /// Returns a new QuerySet containing objects that match the given predicate. diff --git a/QueryKit/SortDescriptor.swift b/QueryKit/SortDescriptor.swift new file mode 100644 index 0000000..72f29db --- /dev/null +++ b/QueryKit/SortDescriptor.swift @@ -0,0 +1,22 @@ +import Foundation + +/// Represents a sort descriptor for a specific model +public struct SortDescriptor { + let sortDescriptor:NSSortDescriptor + + init(sortDescriptor:NSSortDescriptor) { + self.sortDescriptor = sortDescriptor + } +} + +extension Attribute { + /// Returns an ascending sort descriptor for the attribute + public func ascending() -> SortDescriptor { + return SortDescriptor(sortDescriptor: ascending()) + } + + /// Returns a descending sort descriptor for the attribute + public func descending() -> SortDescriptor { + return SortDescriptor(sortDescriptor: descending()) + } +} diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 0e70856..39d8498 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -49,6 +49,17 @@ class QuerySetTests: XCTestCase { XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) } + func testTypeSafeOrderBySortDescriptor() { + let qs = queryset.orderBy { $0.name.ascending() } + XCTAssertTrue(qs.sortDescriptors == [NSSortDescriptor(key: "name", ascending: true)]) + } + + func testTypeSafeOrderBySortDescriptors() { + let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) + let qs = queryset.orderBy { [$0.name.ascending()] } + XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) + } + func testReverseOrdering() { let nameSortDescriptor = NSSortDescriptor(key: "name", ascending: true) let ageSortDescriptor = NSSortDescriptor(key: "age", ascending: true) diff --git a/QueryKitTests/SortDescriptorTests.swift b/QueryKitTests/SortDescriptorTests.swift new file mode 100644 index 0000000..34f43ff --- /dev/null +++ b/QueryKitTests/SortDescriptorTests.swift @@ -0,0 +1,21 @@ +import XCTest +@testable import QueryKit + +class SortDescriptorTests: XCTestCase { + var attribute:Attribute! + + override func setUp() { + super.setUp() + attribute = Attribute("age") + } + + func testAscendingSortDescriptor() { + let sortDescriptor:SortDescriptor = attribute.ascending() + XCTAssertEqual(sortDescriptor.sortDescriptor, NSSortDescriptor(key: "age", ascending: true)) + } + + func testDescendingSortDescriptor() { + let sortDescriptor:SortDescriptor = attribute.descending() + XCTAssertEqual(sortDescriptor.sortDescriptor, NSSortDescriptor(key: "age", ascending: false)) + } +} From f5477e54c3a70803fc17a025db2e0e988cb99152 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 17:30:03 -0700 Subject: [PATCH 29/71] Test type-safe relation filtering --- QueryKit/Attribute.swift | 64 +++++++++++++++------------ QueryKit/ObjectiveC/QKAttribute.swift | 2 +- QueryKit/Predicate.swift | 14 +++--- QueryKit/QuerySet.swift | 2 +- QueryKitTests/AttributeTests.swift | 6 +-- QueryKitTests/PredicateTests.swift | 10 +---- QueryKitTests/QueryKitTests.swift | 60 +++++++++++++++++++++++-- QueryKitTests/QuerySetTests.swift | 17 ++++++- 8 files changed, 122 insertions(+), 53 deletions(-) diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index d453a19..6ac1d64 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -10,87 +10,93 @@ import Foundation /// An attribute, representing an attribute on a model public struct Attribute : Equatable { - public let name:String + public let key:String - public init(_ name:String) { - self.name = name + public init(_ key:String) { + self.key = key } /// Builds a compound attribute with other key paths - public init(attributes:Array) { + public init(attributes:[String]) { self.init(attributes.joinWithSeparator(".")) } /// Returns an expression for the attribute public var expression:NSExpression { - return NSExpression(forKeyPath: name) + return NSExpression(forKeyPath: key) } // MARK: Sorting /// Returns an ascending sort descriptor for the attribute public func ascending() -> NSSortDescriptor { - return NSSortDescriptor(key: name, ascending: true) + return NSSortDescriptor(key: key, ascending: true) } /// Returns a descending sort descriptor for the attribute public func descending() -> NSSortDescriptor { - return NSSortDescriptor(key: name, ascending: false) + return NSSortDescriptor(key: key, ascending: false) } - func expressionForValue(value:AttributeType) -> NSExpression { - // TODO: Find a cleaner implementation - if let value = value as? NSObject { - return NSExpression(forConstantValue: value as NSObject) - } + func expressionForValue(value:AttributeType?) -> NSExpression { + if let value = value { + if let value = value as? NSObject { + return NSExpression(forConstantValue: value as NSObject) + } + + if sizeof(value.dynamicType) == sizeof(uintptr_t) { + let value = unsafeBitCast(value, Optional.self) + if let value = value { + return NSExpression(forConstantValue: value) + } + } - if sizeof(value.dynamicType) == sizeof(uintptr_t) { - let value = unsafeBitCast(value, Optional.self) + let value = unsafeBitCast(value, Optional.self) if let value = value { return NSExpression(forConstantValue: value) } } - let value = unsafeBitCast(value, Optional.self) - if let value = value { - return NSExpression(forConstantValue: value) - } - return NSExpression(forConstantValue: NSNull()) } + + /// Builds a compound attribute by the current attribute with the given attribute + public func attribute(attribute:Attribute) -> Attribute { + return Attribute(attributes: [key, attribute.key]) + } } /// Returns true if two attributes have the same name public func == (lhs: Attribute, rhs: Attribute) -> Bool { - return lhs.name == rhs.name + return lhs.key == rhs.key } -public func == (left: Attribute, right: AttributeType) -> NSPredicate { +public func == (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression == left.expressionForValue(right) } -public func != (left: Attribute, right: AttributeType) -> NSPredicate { +public func != (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression != left.expressionForValue(right) } -public func > (left: Attribute, right: AttributeType) -> NSPredicate { +public func > (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression > left.expressionForValue(right) } -public func >= (left: Attribute, right: AttributeType) -> NSPredicate { +public func >= (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression >= left.expressionForValue(right) } -public func < (left: Attribute, right: AttributeType) -> NSPredicate { +public func < (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression < left.expressionForValue(right) } -public func <= (left: Attribute, right: AttributeType) -> NSPredicate { +public func <= (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression <= left.expressionForValue(right) } -public func ~= (left: Attribute, right: AttributeType) -> NSPredicate { +public func ~= (left: Attribute, right: AttributeType?) -> NSPredicate { return left.expression ~= left.expressionForValue(right) } @@ -125,9 +131,9 @@ public extension QuerySet { // MARK: Collections public func count(attribute:Attribute) -> Attribute { - return Attribute(attributes: [attribute.name, "@count"]) + return Attribute(attributes: [attribute.key, "@count"]) } public func count(attribute:Attribute) -> Attribute { - return Attribute(attributes: [attribute.name, "@count"]) + return Attribute(attributes: [attribute.key, "@count"]) } diff --git a/QueryKit/ObjectiveC/QKAttribute.swift b/QueryKit/ObjectiveC/QKAttribute.swift index d3bc9e2..fd3a5ba 100644 --- a/QueryKit/ObjectiveC/QKAttribute.swift +++ b/QueryKit/ObjectiveC/QKAttribute.swift @@ -2,7 +2,7 @@ import Foundation extension Attribute { public func asQKAttribute() -> QKAttribute { - return QKAttribute(name: name) + return QKAttribute(name: key) } } diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index 9ec4db6..c67a411 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -34,31 +34,31 @@ public struct Predicate { } } -public func == (left: Attribute, right: AttributeType) -> Predicate { +public func == (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left == right) } -public func != (left: Attribute, right: AttributeType) -> Predicate { +public func != (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left != right) } -public func > (left: Attribute, right: AttributeType) -> Predicate { +public func > (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left > right) } -public func >= (left: Attribute, right: AttributeType) -> Predicate { +public func >= (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left >= right) } -public func < (left: Attribute, right: AttributeType) -> Predicate { +public func < (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left < right) } -public func <= (left: Attribute, right: AttributeType) -> Predicate { +public func <= (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left <= right) } -public func ~= (left: Attribute, right: AttributeType) -> Predicate { +public func ~= (left: Attribute, right: AttributeType?) -> Predicate { return Predicate(predicate: left ~= right) } diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index f5ad459..52ae581 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -10,7 +10,7 @@ import Foundation import CoreData /// Represents a lazy database lookup for a set of objects. -public class QuerySet : SequenceType, Equatable { +public class QuerySet : Equatable, SequenceType { /// Returns the managed object context that will be used to execute any requests. public let context:NSManagedObjectContext diff --git a/QueryKitTests/AttributeTests.swift b/QueryKitTests/AttributeTests.swift index 90ff93f..65498a2 100644 --- a/QueryKitTests/AttributeTests.swift +++ b/QueryKitTests/AttributeTests.swift @@ -17,8 +17,8 @@ class AttributeTests: XCTestCase { attribute = Attribute("age") } - func testAttributeHasName() { - XCTAssertEqual(attribute.name, "age") + func testAttributeHasKey() { + XCTAssertEqual(attribute.key, "age") } func testAttributeExpression() { @@ -32,7 +32,7 @@ class AttributeTests: XCTestCase { func testCompoundAttributeCreation() { let personCompanyNameAttribute = Attribute(attributes:["company", "name"]) - XCTAssertEqual(personCompanyNameAttribute.name, "company.name") + XCTAssertEqual(personCompanyNameAttribute.key, "company.name") XCTAssertEqual(personCompanyNameAttribute.expression.keyPath, "company.name") } diff --git a/QueryKitTests/PredicateTests.swift b/QueryKitTests/PredicateTests.swift index a87f66f..5f93c8b 100644 --- a/QueryKitTests/PredicateTests.swift +++ b/QueryKitTests/PredicateTests.swift @@ -86,14 +86,8 @@ class PredicateTests: XCTestCase { XCTAssertEqual(predicate.predicate, NSPredicate(format:"age BETWEEN %@", [5, 10])) } - func testOptionalEqualityOperator() { - let attribute = Attribute("name") - let predicate:Predicate = (attribute == "kyle") - XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == 'kyle'")) - } - - func testOptionalNSObjectEqualityOperator() { - let attribute = Attribute("name") + func testNSObjectEqualityOperator() { + let attribute = Attribute("name") let predicate:Predicate = (attribute == "kyle") XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == 'kyle'")) } diff --git a/QueryKitTests/QueryKitTests.swift b/QueryKitTests/QueryKitTests.swift index 38ba892..3b9f62f 100644 --- a/QueryKitTests/QueryKitTests.swift +++ b/QueryKitTests/QueryKitTests.swift @@ -12,6 +12,7 @@ import CoreData @objc(Person) class Person : NSManagedObject { @NSManaged var name:String + @NSManaged var company:Company? class var entityName:String { return "Person" @@ -20,6 +21,32 @@ import CoreData class var name:Attribute { return Attribute("name") } + + class var company:Attribute { + return Attribute("company") + } +} + +@objc(Company) class Company : NSManagedObject { + @NSManaged var name:String + + class var entityName:String { + return "Company" + } + + class var name:Attribute { + return Attribute("name") + } + + class func create(context:NSManagedObjectContext) -> Company { + return NSEntityDescription.insertNewObjectForEntityForName(Company.entityName, inManagedObjectContext: context) as! Company + } +} + +extension Attribute where AttributeType: Company { + var name:Attribute { + return attribute(AttributeType.name) + } } extension Person { @@ -29,18 +56,43 @@ extension Person { } func managedObjectModel() -> NSManagedObjectModel { + let companyEntity = NSEntityDescription() + companyEntity.name = Company.entityName + companyEntity.managedObjectClassName = "Company" + let personEntity = NSEntityDescription() personEntity.name = Person.entityName personEntity.managedObjectClassName = "Person" + let companyNameAttribute = NSAttributeDescription() + companyNameAttribute.name = "name" + companyNameAttribute.attributeType = NSAttributeType.StringAttributeType + companyNameAttribute.optional = false + + let companyPeopleAttribute = NSRelationshipDescription() + companyPeopleAttribute.name = "members" + companyPeopleAttribute.maxCount = 0 + companyPeopleAttribute.destinationEntity = personEntity + let personNameAttribute = NSAttributeDescription() personNameAttribute.name = "name" personNameAttribute.attributeType = NSAttributeType.StringAttributeType personNameAttribute.optional = false - personEntity.properties = [personNameAttribute] + + let personCompanyRelation = NSRelationshipDescription() + personCompanyRelation.name = "company" + personCompanyRelation.destinationEntity = companyEntity + personCompanyRelation.maxCount = 1 + personCompanyRelation.optional = true + + companyPeopleAttribute.inverseRelationship = personCompanyRelation + personCompanyRelation.inverseRelationship = companyPeopleAttribute + + companyEntity.properties = [companyNameAttribute, companyPeopleAttribute] + personEntity.properties = [personNameAttribute, personCompanyRelation] let model = NSManagedObjectModel() - model.entities = [personEntity] + model.entities = [personEntity, companyEntity] return model } @@ -50,7 +102,9 @@ func persistentStoreCoordinator() -> NSPersistentStoreCoordinator { let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model) do { try persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil) - } catch _ { + } catch { + print(error) + fatalError() } return persistentStoreCoordinator } diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 39d8498..797ba90 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -21,9 +21,16 @@ class QuerySetTests: XCTestCase { context = NSManagedObjectContext() context.persistentStoreCoordinator = persistentStoreCoordinator() + let company = Company.create(context) + company.name = "Cocode" + for name in ["Kyle", "Orta", "Ayaka", "Mark", "Scott"] { let person = Person.create(context) person.name = name + + if name == "Kyle" { + person.company == "Cocode" + } } try! context.save() @@ -93,11 +100,19 @@ class QuerySetTests: XCTestCase { } func testTypeSafeFilter() { - let qs = queryset.filter { $0.name == "Kyle" } + let qs:QuerySet = queryset.filter { $0.name == "Kyle" } XCTAssertEqual(qs.predicate?.description, "name == \"Kyle\"") } + func testTypeSafeRelatedFilterPredicate() { + let at = Attribute("company") + XCTAssertEqual(at.name.key, "company.name") + let qs = queryset.filter { $0.company.name == "Cocode" } + + XCTAssertEqual(qs.predicate?.description, "company.name == \"Cocode\"") + } + // MARK: Exclusion func testExcludePredicate() { From b38319d2338219c7084e76c0fc7157fb0f867cbb Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 17:32:16 -0700 Subject: [PATCH 30/71] [QuerySet] No longer conform to SequenceType Explicit conversion is preferred --- QueryKit/QuerySet.swift | 13 +------------ QueryKitTests/QuerySetTests.swift | 15 +-------------- README.md | 10 ++-------- 3 files changed, 4 insertions(+), 34 deletions(-) diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 52ae581..a6733ad 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -10,7 +10,7 @@ import Foundation import CoreData /// Represents a lazy database lookup for a set of objects. -public class QuerySet : Equatable, SequenceType { +public class QuerySet : Equatable { /// Returns the managed object context that will be used to execute any requests. public let context:NSManagedObjectContext @@ -231,17 +231,6 @@ extension QuerySet { return deletedCount } - - // MARK: Sequence - - public func generate() -> IndexingGenerator> { - do { - let generator = try self.array().generate() - return generator - } catch { - return [].generate() - } - } } /// Returns true if the two given querysets are equivilent diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 797ba90..69f322b 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -100,7 +100,7 @@ class QuerySetTests: XCTestCase { } func testTypeSafeFilter() { - let qs:QuerySet = queryset.filter { $0.name == "Kyle" } + let qs = queryset.filter { $0.name == "Kyle" } XCTAssertEqual(qs.predicate?.description, "name == \"Kyle\"") } @@ -249,17 +249,4 @@ class QuerySetTests: XCTestCase { XCTAssertEqual(deletedCount, 2) XCTAssertEqual(count, 3) } - - // MARK: Sequence - - func testSequence() { - let qs = queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) - var objects = [Person]() - - for object in qs { - objects.append(object) - } - - XCTAssertEqual(objects.count, 5) - } } diff --git a/README.md b/README.md index bd8eeb1..515e9d4 100644 --- a/README.md +++ b/README.md @@ -91,20 +91,14 @@ queryset[0..5] ##### Multiple objects -A QuerySet is utterable, and it executes the query when you iterate over it. For example: +You can convert a QuerySet to an array using the `array()` function. For example: ```swift -for person in queryset { +for person in try! queryset.array() { println("Hello \(person.name).") } ``` -You can also convert the QuerySet to an Array: - -```swift -queryset.array() -``` - ##### First object ```swift From c7034c0d8d17461f5cfb2b1503ef44e7315a8b53 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 21:42:10 -0700 Subject: [PATCH 31/71] Release 0.11.0-beta.2 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index fa7d5d6..93b87ce 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.0-beta.1' + spec.version = '0.11.0-beta.2' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 3d50c49f4e570597b974ff351a9dc6be15b19c6c Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 21:52:19 -0700 Subject: [PATCH 32/71] Simplify podspec --- QueryKit.podspec | 45 +++++++---------------------------- QueryKit/Attribute.swift | 8 ------- QueryKit/Expression.swift | 8 ------- QueryKit/Predicate.swift | 9 +------ QueryKit/QueryKit.h | 8 ------- QueryKit/QuerySet.swift | 8 ------- QueryKit/SortDescriptor.swift | 1 + 7 files changed, 10 insertions(+), 77 deletions(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 93b87ce..58ad97b 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -5,54 +5,25 @@ Pod::Spec.new do |spec| spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } - spec.social_media_url = 'http://twitter.com/QueryKit' + spec.social_media_url = 'https://twitter.com/QueryKit' spec.source = { :git => 'https://github.com/QueryKit/QueryKit.git', :tag => "#{spec.version}" } - spec.source_files = 'QueryKit/QueryKit.h' spec.requires_arc = true spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' + spec.frameworks = 'CoreData' spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.dependency 'QueryKit/Attribute/ObjectiveC' - objc_spec.dependency 'QueryKit/QuerySet/ObjectiveC' + objc_spec.source_files = 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' end spec.subspec 'Swift' do |swift_spec| - swift_spec.dependency 'QueryKit/Attribute/Swift' - swift_spec.dependency 'QueryKit/QuerySet/Swift' + swift_spec.source_files = 'QueryKit/*.swift' end - spec.subspec 'Attribute' do |attribute_spec| - attribute_spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.source_files = 'QueryKit/ObjectiveC/QKAttribute.{h,m}' - end - - attribute_spec.subspec 'Swift' do |swift_spec| - swift_spec.dependency 'QueryKit/QuerySet/Swift' - swift_spec.source_files = 'QueryKit/{Attribute,Expression,Predicate}.swift' - end - - attribute_spec.subspec 'Bridge' do |bridge_spec| - bridge_spec.dependency 'QueryKit/Attribute/Swift' - bridge_spec.dependency 'QueryKit/Attribute/ObjectiveC' - bridge_spec.source_files = 'QueryKit/ObjectiveC/QKAttribute.swift' - end - end - - spec.subspec 'QuerySet' do |queryset_spec| - queryset_spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.source_files = 'QueryKit/ObjectiveC/QKQuerySet.{h,m}' - end - - queryset_spec.subspec 'Swift' do |swift_spec| - swift_spec.source_files = 'QueryKit/QuerySet.swift' - end - - queryset_spec.subspec 'Bridge' do |bridge_spec| - bridge_spec.dependency 'QueryKit/QuerySet/Swift' - bridge_spec.dependency 'QueryKit/QuerySet/ObjectiveC' - bridge_spec.source_files = 'QueryKit/ObjectiveC/QKQuerySet.swift' - end + spec.subspec 'Bridge' do |bridge_spec| + bridge_spec.dependency 'QueryKit/Swift' + bridge_spec.dependency 'QueryKit/ObjectiveC' + bridge_spec.source_files = 'QueryKit/ObjectiveC/QK{Attribute,QuerySet}.swift' end end diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index 6ac1d64..fc9e210 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -1,11 +1,3 @@ -// -// Attribute.swift -// QueryKit -// -// Created by Kyle Fuller on 19/06/2014. -// -// - import Foundation /// An attribute, representing an attribute on a model diff --git a/QueryKit/Expression.swift b/QueryKit/Expression.swift index 8e803b3..b91507c 100644 --- a/QueryKit/Expression.swift +++ b/QueryKit/Expression.swift @@ -1,11 +1,3 @@ -// -// Expression.swift -// QueryKit -// -// Created by Kyle Fuller on 06/07/2014. -// -// - import Foundation /// Returns an equality predicate for the two given expressions diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index c67a411..2a97b0a 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -1,12 +1,5 @@ -// -// Predicate.swift -// QueryKit -// -// Created by Kyle Fuller on 19/06/2014. -// -// - import Foundation +import CoreData /// Returns an and predicate from the given predicates public func && (left: NSPredicate, right: NSPredicate) -> NSPredicate { diff --git a/QueryKit/QueryKit.h b/QueryKit/QueryKit.h index 6423d79..f4d7312 100644 --- a/QueryKit/QueryKit.h +++ b/QueryKit/QueryKit.h @@ -1,11 +1,3 @@ -// -// QueryKit.h -// QueryKit -// -// Created by Kyle Fuller on 19/06/2014. -// -// - #import //! Project version number for QueryKit. diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index a6733ad..e55d7e5 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -1,11 +1,3 @@ -// -// QuerySet.swift -// QueryKit -// -// Created by Kyle Fuller on 06/07/2014. -// -// - import Foundation import CoreData diff --git a/QueryKit/SortDescriptor.swift b/QueryKit/SortDescriptor.swift index 72f29db..96bfc25 100644 --- a/QueryKit/SortDescriptor.swift +++ b/QueryKit/SortDescriptor.swift @@ -1,4 +1,5 @@ import Foundation +import CoreData /// Represents a sort descriptor for a specific model public struct SortDescriptor { From 2abdb9cf5ab852f102119cd8ad528e880174dd26 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 8 Sep 2015 22:06:14 -0700 Subject: [PATCH 33/71] Release 0.11.0-beta.3 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 58ad97b..51a97ee 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.0-beta.2' + spec.version = '0.11.0-beta.3' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 1d91b6d935332f6004c9047cec54bed1cb403861 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 09:31:39 -0700 Subject: [PATCH 34/71] Release 0.11.0-beta.4 --- QueryKit.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 51a97ee..da4f726 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.0-beta.3' + spec.version = '0.11.0-beta.4' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } @@ -13,7 +13,7 @@ Pod::Spec.new do |spec| spec.frameworks = 'CoreData' spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.source_files = 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' + objc_spec.source_files = 'QueryKit/QueryKit.h', 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' end spec.subspec 'Swift' do |swift_spec| From fb881cde6febc96558acd76d8643e539556bd81d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 16:12:02 -0700 Subject: [PATCH 35/71] Add watchOS support --- .travis.yml | 1 + .../UniversalFramework_Base.xcconfig | 19 +++++++++++-------- .../UniversalFramework_Framework.xcconfig | 16 +++++++++------- .../UniversalFramework_Test.xcconfig | 16 ++++++++-------- QueryKit.podspec | 1 + 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index db99e1d..32535ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,6 @@ script: - set -o pipefail - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c + - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit build -sdk watchos | xcpretty -c - pod lib lint QueryKit.podspec diff --git a/Configurations/UniversalFramework_Base.xcconfig b/Configurations/UniversalFramework_Base.xcconfig index b6fe0ab..a82fa66 100644 --- a/Configurations/UniversalFramework_Base.xcconfig +++ b/Configurations/UniversalFramework_Base.xcconfig @@ -1,18 +1,21 @@ // -// UniversalFramework_Base.xcconfig -// QueryKit +// Put this file alongside to the other both, as it contains what +// both have in common. Don't rename this file. // -// Created by Marius Rackwitz on 29/11/14. -// Copyright (c) 2014 Marius Rackwitz. All rights reserved. +// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. // // Make it universal -SUPPORTED_PLATFORMS = iphonesimulator iphoneos macosx -VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s -VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 +SUPPORTED_PLATFORMS = macosx iphonesimulator iphoneos watchos watchsimulator VALID_ARCHS[sdk=macosx*] = i386 x86_64 +VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s +VALID_ARCHS[sdk=iphonesimulator*] = arm64 armv7 armv7s +VALID_ARCHS[sdk=watchos*] = armv7k +VALID_ARCHS[sdk=watchsimulator*] = armv7k // Dynamic linking uses different default copy paths +LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' diff --git a/Configurations/UniversalFramework_Framework.xcconfig b/Configurations/UniversalFramework_Framework.xcconfig index ead2bdf..c0c1f68 100644 --- a/Configurations/UniversalFramework_Framework.xcconfig +++ b/Configurations/UniversalFramework_Framework.xcconfig @@ -1,18 +1,20 @@ // -// UniversalFramework_Framework.xcconfig -// QueryKit +// Inherit from this config in your framework target. // -// Created by Marius Rackwitz on 29/11/14. -// Copyright (c) 2014 Marius Rackwitz. All rights reserved. +// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. // #include "UniversalFramework_Base.xcconfig" +// OSX-specific default settings +FRAMEWORK_VERSION[sdk=macosx*] = A +COMBINE_HIDPI_IMAGES[sdk=macosx*] = YES + // iOS-specific default settings CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*] = 1,2 TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2 -// OSX-specific default settings -FRAMEWORK_VERSION[sdk=macosx*] = A -COMBINE_HIDPI_IMAGES[sdk=macosx*] = YES +// Watch-specific default settings +TARGETED_DEVICE_FAMILY[sdk=watchsimulator*] = 4 +TARGETED_DEVICE_FAMILY[sdk=watch*] = 4 diff --git a/Configurations/UniversalFramework_Test.xcconfig b/Configurations/UniversalFramework_Test.xcconfig index 26a6518..d225d11 100644 --- a/Configurations/UniversalFramework_Test.xcconfig +++ b/Configurations/UniversalFramework_Test.xcconfig @@ -1,16 +1,16 @@ // -// UniversalFramework_Test.xcconfig -// QueryKit +// Inherit from this config in the test target for your framework. // -// Created by Marius Rackwitz on 29/11/14. -// Copyright (c) 2014 Marius Rackwitz. All rights reserved. +// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. // #include "UniversalFramework_Base.xcconfig" -FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '$(SDKROOT)/Developer/Library/Frameworks' -FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '$(SDKROOT)/Developer/Library/Frameworks' -FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(inherited) '$(DEVELOPER_FRAMEWORKS_DIR)' +FRAMEWORK_SEARCH_PATHS = $(inherited) '$(PLATFORM_DIR)/Developer/Library/Frameworks' // Yep. -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' \ No newline at end of file +LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/QueryKit.podspec b/QueryKit.podspec index da4f726..b709123 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -10,6 +10,7 @@ Pod::Spec.new do |spec| spec.requires_arc = true spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' + spec.watchos.deployment_target = '2.0' spec.frameworks = 'CoreData' spec.subspec 'ObjectiveC' do |objc_spec| From 92547c2a51563b9da36e9941dad269e2a4e9b7d9 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 17:22:22 -0700 Subject: [PATCH 36/71] [README] Swift 2.0 API changes --- README.md | 142 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 515e9d4..fd382a6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -QueryKit Logo +QueryKit Logo # QueryKit @@ -8,17 +8,38 @@ QueryKit, a simple type-safe Core Data query language. ## Usage -### QuerySet +To get the most out of QueryKit, and to get full type-safe queries, you can +adds extensions for your models providing properties which describe your +models. You can use [querykit-cli](https://github.com/QueryKit/querykit-cli) +to generate these automatically. -A QuerySet represents a collection of objects from your Core Data Store. It can have zero, one or many filters. Filters narrow down the query results based on the given parameters. +An extension for our a `Person` model might look as follows: -#### Retrieving all objects +```swift +extension User { + static var name:Attribute { return Attribute("name") } + static var age:Attribute { return Attribute("age") } +} +``` + +This provides static properties on our User model which represent each property +on our Core Data model, these can be used to construct predicates and sort +descriptors with compile time safety, without stringly typing them +into your application. ```swift -let queryset = QuerySet(context, "Person") +let namePredicate = Person.name == "Kyle" +let agePredicate = Person.age > 25 +let ageSortDescriptor = Person.age.descending() ``` -**NOTE**: *It’s recommend to implement a type type-safe `queryset` method on your model.* +### QuerySet + +A QuerySet represents a collection of objects from your Core Data Store. +It can have zero, one or many filters. Filters narrow down the query +results based on the given parameters. + +#### Retrieving all objects ```swift let queryset = Person.queryset(context) @@ -27,66 +48,72 @@ let queryset = Person.queryset(context) #### Retrieving specific objects with filters You can filter a QuerySet using the `filter` and `exclude` methods, which -accept a predicate and return a new QuerySet. +accept a closure passing the model type allowing you to access the +type-safe attributes. + +The `filter` and `exclude` methods return brand new QuerySet's including your filter. ```swift -queryset.filter(NSPredicate(format: "name == %@", "Kyle")) -queryset.exclude(NSPredicate(format: "age > 21")) +queryset.filter { $0.name == "Kyle" } +queryset.exclude { $0.age > 25 } ``` -**NOTE**: *You can define [type-safe methods](https://github.com/QueryKit/TodoExample/blob/master/Todo/Model/Generated/_Task.swift#L14-26) on your models, or use the [mogenerator template](https://github.com/QueryKit/mogenerator-template) to generate these.* +You can also use standard `NSPredicate` if you want to construct complicated +queries or do not wish to use the type-safe properties. ```swift -queryset.filter(Person.attributes.name == "Kyle") -queryset.exclude(Person.attributes.age > 21) +queryset.filter(NSPredicate(format: "name == '%@'", "Kyle")) +queryset.exclude(NSPredicate(format: "age > 25")) ``` ##### Chaining filters -The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example: +The result of refining a QuerySet is itself a QuerySet, so it’s possible +to chain refinements together. For example: ```swift -queryset.filter(Person.attributes.name == "Kyle") - .exclude(Person.attributes.age > 21) - .filter(Person.attributes.isEmployed) +queryset.filter { $0.name == "Kyle" } + .exclude { $0.age < 25 } + .filter { $0.isEmployed } ``` -Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused. +Each time you refine a QuerySet, you get a brand-new QuerySet that is in +no way bound to the previous QuerySet. Each refinement creates a separate +and distinct QuerySet that can be stored, used and reused. #### QuerySets are lazy -A QuerySet is lazy, creating a QuerySet doesn’t involve querying Core Data. QueryKit won’t actually execute the query until the QuerySet is *evaluated*. +A QuerySet is lazy, creating a QuerySet doesn’t involve querying +Core Data. QueryKit won’t actually execute the query until the +QuerySet is *evaluated*. -#### Slicing +#### Ordering -Using slicing, you can limit your QuerySet to a certain number of results. +You can order a QuerySet's results by using the `orderBy` function which +accepts a closure where you can return a sort descriptor: ```swift -Person.queryset(context)[0..<10] +queryset.orderBy { $0.name.ascending() } ``` -**NOTE**: *Remember, QuerySets are lazily evaluated. Slicing doesn’t evaluate the query.* - -#### Ordering - -You can order a QuerySet's results by using the `orderBy` method which accepts -a collection of sort descriptors: +You may also pass in an `NSSortDescriptor` if you would rather. -```swift -queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) +``` queryset.orderBy(Person.name.ascending) -queryset.orderBy([Person.name.ascending, Person.age.descending]) +queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) ``` #### Slicing -You can use slicing to limit a queryset to a range. For example, to get the -first 5 items: +Using slicing, a QuerySet's results can be limited to a specified range. For +example, to get the first 5 items in our QuerySet: ```swift queryset[0..5] ``` +**NOTE**: *Remember, QuerySets are lazily evaluated. Slicing doesn’t evaluate the query.* + #### Fetching ##### Multiple objects @@ -102,54 +129,67 @@ for person in try! queryset.array() { ##### First object ```swift -var kyle = Person.queryset(context).filter(Person.name == "Kyle").first() +let kyle = try? queryset.first() ``` ##### Last object ```swift -var kyle = Person.queryset(context).filter(Person.name == "Kyle").last() +let kyle = try? queryset.last() ``` ##### Object at index ```swift -var orta = queryset.object(3) +let katie = try? queryset.object(3) ``` ##### Count ```swift -queryset.count() +let numberOfPeople = try? queryset.count() ``` ##### Deleting This method immediately deletes the objects in your queryset and returns a -count and an error if the operation failed. +count or an error if the operation failed. ```swift -queryset.delete() +let deleted = try? queryset.delete() ``` #### Attribute -The `Attribute` is a generic structure for creating predicates in a type-safe manner. +The `Attribute` is a generic structure for creating predicates in a +type-safe manner as shown at the start of the README. ```swift let name = Attribute("name") let age = Attribute("age") +``` + +##### Operators + +QueryKit provides custom operator functions allowing you to create predicates. +``` +// Name is equal to Kyle name == "Kyle" + +// Name is either equal to Kyle or Katie name << ["Kyle", "Katie"] +// Age is equal to 27 age == 27 + +// Age is more than or equal to 25 age >= 25 + +// Age is within the range 22 to 30. age << (22...30) ``` -##### Operators - The following types of comparisons are supported using Attribute: | Comparison | Meaning | @@ -165,22 +205,26 @@ The following types of comparisons are supported using Attribute: | << | x IN y, where y is an array | | << | x BETWEEN y, where y is a range | -#### Predicate extensions +##### Predicate extensions -We've also extended NSPredicate to add support for the `!`, `&&` and `||` operators for joining predicates together. - -```swift -NSPredicate(format:"name == Kyle") || NSPredicate(format:"name == Katie") -NSPredicate(format:"age >= 21") && !NSPredicate(format:"name == Kyle") -``` +QueryKit provides the `!`, `&&` and `||` operators for joining multiple predicates together. ```swift +// Persons name is Kyle or Katie Person.name == "Kyle" || Person.name == "Katie" -Person.age >= 21 || Person.name != "Kyle" + +// Persons age is more than 25 and their name is Kyle +Person.age >= 25 && Person.name == "Kyle" + +// Persons name is not Kyle +!(Person.name == "Kyle") ``` ## Installation +[CocoaPods](http://cocoapods.org) is the recommended way to add QueryKit to +your project, you may also use Carthage. + ```ruby pod 'QueryKit' ``` From 3e9d1162605b8bcccbecfea153f900792c53135d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 17:25:55 -0700 Subject: [PATCH 37/71] [README] RFC2119 --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index fd382a6..c577b22 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ QueryKit, a simple type-safe Core Data query language. ## Usage -To get the most out of QueryKit, and to get full type-safe queries, you can +To get the most out of QueryKit, and to get full type-safe queries, you may adds extensions for your models providing properties which describe your -models. You can use [querykit-cli](https://github.com/QueryKit/querykit-cli) +models. You may use [querykit-cli](https://github.com/QueryKit/querykit-cli) to generate these automatically. An extension for our a `Person` model might look as follows: @@ -23,7 +23,7 @@ extension User { ``` This provides static properties on our User model which represent each property -on our Core Data model, these can be used to construct predicates and sort +on our Core Data model, these may be used to construct predicates and sort descriptors with compile time safety, without stringly typing them into your application. @@ -36,7 +36,7 @@ let ageSortDescriptor = Person.age.descending() ### QuerySet A QuerySet represents a collection of objects from your Core Data Store. -It can have zero, one or many filters. Filters narrow down the query +It may have zero, one or many filters. Filters narrow down the query results based on the given parameters. #### Retrieving all objects @@ -47,7 +47,7 @@ let queryset = Person.queryset(context) #### Retrieving specific objects with filters -You can filter a QuerySet using the `filter` and `exclude` methods, which +You may filter a QuerySet using the `filter` and `exclude` methods, which accept a closure passing the model type allowing you to access the type-safe attributes. @@ -58,7 +58,7 @@ queryset.filter { $0.name == "Kyle" } queryset.exclude { $0.age > 25 } ``` -You can also use standard `NSPredicate` if you want to construct complicated +You may also use standard `NSPredicate` if you want to construct complicated queries or do not wish to use the type-safe properties. ```swift @@ -79,7 +79,7 @@ queryset.filter { $0.name == "Kyle" } Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate -and distinct QuerySet that can be stored, used and reused. +and distinct QuerySet that may be stored, used and reused. #### QuerySets are lazy @@ -89,8 +89,9 @@ QuerySet is *evaluated*. #### Ordering -You can order a QuerySet's results by using the `orderBy` function which -accepts a closure where you can return a sort descriptor: +You may order a QuerySet's results by using the `orderBy` function which +accepts a closure passing the model type, and expects a sort descriptor in +return. ```swift queryset.orderBy { $0.name.ascending() } @@ -98,14 +99,14 @@ queryset.orderBy { $0.name.ascending() } You may also pass in an `NSSortDescriptor` if you would rather. -``` -queryset.orderBy(Person.name.ascending) +```swift +queryset.orderBy(Person.name.ascending()) queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) ``` #### Slicing -Using slicing, a QuerySet's results can be limited to a specified range. For +Using slicing, a QuerySet's results may be limited to a specified range. For example, to get the first 5 items in our QuerySet: ```swift @@ -118,7 +119,7 @@ queryset[0..5] ##### Multiple objects -You can convert a QuerySet to an array using the `array()` function. For example: +You may convert a QuerySet to an array using the `array()` function. For example: ```swift for person in try! queryset.array() { From 9471a1228c5de0c8d87c116037c54ee326a29dd2 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 17:27:04 -0700 Subject: [PATCH 38/71] [README] Use Swift code-blocks --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c577b22..6b78704 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ let age = Attribute("age") QueryKit provides custom operator functions allowing you to create predicates. -``` +```swift // Name is equal to Kyle name == "Kyle" From a165ae9a749226da3cb76b0025ed6512f4c557b0 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 17:27:25 -0700 Subject: [PATCH 39/71] [travis] Allow warnings (homepage fails) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 32535ec..1ac7b12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,5 @@ script: - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit build -sdk watchos | xcpretty -c - - pod lib lint QueryKit.podspec + - pod lib lint --allow-warnings From 728b828aa213aa5bf61ebe854714599469f3cf3c Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 17:28:26 -0700 Subject: [PATCH 40/71] Release 0.11.0 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index b709123..13473d9 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.0-beta.4' + spec.version = '0.11.0' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 53515a882318c443605e1793c06da4a16e74cf6a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Wed, 9 Sep 2015 23:48:30 -0700 Subject: [PATCH 41/71] [README] Minor grammar fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b78704..c7ca46c 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ QueryKit, a simple type-safe Core Data query language. ## Usage To get the most out of QueryKit, and to get full type-safe queries, you may -adds extensions for your models providing properties which describe your -models. You may use [querykit-cli](https://github.com/QueryKit/querykit-cli) +add extensions for your Core Data models providing properties which describe +your models. You may use [querykit-cli](https://github.com/QueryKit/querykit-cli) to generate these automatically. An extension for our a `Person` model might look as follows: From 75a3df844d718bb79a8c360dcc0b69e57597ef20 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 20 Sep 2015 12:13:55 -0700 Subject: [PATCH 42/71] Collapse Objective-C code Due to cocoadocs thinking we're a Objective-C pod, removing some lines --- QueryKit/ObjectiveC/QKAttribute.m | 109 +++++------------------------- QueryKit/ObjectiveC/QKQuerySet.m | 7 +- 2 files changed, 21 insertions(+), 95 deletions(-) diff --git a/QueryKit/ObjectiveC/QKAttribute.m b/QueryKit/ObjectiveC/QKAttribute.m index dc0910e..dd90e2e 100644 --- a/QueryKit/ObjectiveC/QKAttribute.m +++ b/QueryKit/ObjectiveC/QKAttribute.m @@ -103,18 +103,9 @@ - (NSUInteger)length { #pragma mark - Comparison -- (NSPredicate *)predicateWithRightExpression:(NSExpression *)expression - modifier:(NSComparisonPredicateModifier)modifier - type:(NSPredicateOperatorType)type - options:(NSComparisonPredicateOptions)options -{ +- (NSPredicate *)predicateWithRightExpression:(NSExpression *)expression modifier:(NSComparisonPredicateModifier)modifier type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options { NSExpression *leftExpression = [self expression]; - - return [NSComparisonPredicate predicateWithLeftExpression:leftExpression - rightExpression:expression - modifier:modifier - type:type - options:options]; + return [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression:expression modifier:modifier type:type options:options]; } @end @@ -123,11 +114,7 @@ @implementation QKAttribute (Predicate) - (NSPredicate *)equal:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:options]; } - (NSPredicate *)equal:(id)value { @@ -136,11 +123,7 @@ - (NSPredicate *)equal:(id)value { - (NSPredicate *)notEqual:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSNotEqualToPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSNotEqualToPredicateOperatorType options:options]; } - (NSPredicate *)notEqual:(id)value { @@ -149,11 +132,7 @@ - (NSPredicate *)notEqual:(id)value { - (NSPredicate *)beginsWith:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSBeginsWithPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSBeginsWithPredicateOperatorType options:options]; } - (NSPredicate *)beginsWith:(id)value { @@ -162,11 +141,7 @@ - (NSPredicate *)beginsWith:(id)value { - (NSPredicate *)endsWith:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEndsWithPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEndsWithPredicateOperatorType options:options]; } - (NSPredicate *)endsWith:(id)value { @@ -175,11 +150,7 @@ - (NSPredicate *)endsWith:(id)value { - (NSPredicate *)like:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLikePredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLikePredicateOperatorType options:options]; } - (NSPredicate *)like:(id)value { @@ -188,11 +159,7 @@ - (NSPredicate *)like:(id)value { - (NSPredicate *)matches:(id)value options:(NSComparisonPredicateOptions)options { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSMatchesPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSMatchesPredicateOperatorType options:options]; } - (NSPredicate *)matches:(id)value { @@ -201,47 +168,27 @@ - (NSPredicate *)matches:(id)value { - (NSPredicate *)greaterThan:(id)value { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSGreaterThanPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:0]; } - (NSPredicate *)greaterThanOrEqualTo:(id)value { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSGreaterThanOrEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSGreaterThanOrEqualToPredicateOperatorType options:0]; } - (NSPredicate *)lessThan:(id)value { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLessThanPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLessThanPredicateOperatorType options:0]; } - (NSPredicate *)lessThanOrEqualTo:(id)value { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSLessThanOrEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLessThanOrEqualToPredicateOperatorType options:0]; } - (NSPredicate *)isNil { NSExpression *expression = [NSExpression expressionForConstantValue:nil]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; } - (NSPredicate *)between:(id)minimumValue and:(id)maxiumValue { @@ -249,33 +196,21 @@ - (NSPredicate *)between:(id)minimumValue and:(id)maxiumValue { NSParameterAssert(maxiumValue != nil); NSExpression *expression = [NSExpression expressionForConstantValue:@[minimumValue, maxiumValue]]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSBetweenPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSBetweenPredicateOperatorType options:0]; } - (NSPredicate *)in:(id)set { NSParameterAssert(set != nil); NSExpression *expression = [NSExpression expressionForConstantValue:set]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSInPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0]; } - (NSPredicate *)contains:(id)value options:(NSComparisonPredicateOptions)options { NSParameterAssert(value != nil); NSExpression *expression = [NSExpression expressionForConstantValue:value]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSContainsPredicateOperatorType - options:options]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSContainsPredicateOperatorType options:options]; } - (NSPredicate *)contains:(id)value { @@ -284,20 +219,12 @@ - (NSPredicate *)contains:(id)value { - (NSPredicate *)isYes { NSExpression *expression = [NSExpression expressionForConstantValue:@YES]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; } - (NSPredicate *)isNo { NSExpression *expression = [NSExpression expressionForConstantValue:@NO]; - - return [self predicateWithRightExpression:expression - modifier:NSDirectPredicateModifier - type:NSEqualToPredicateOperatorType - options:0]; + return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; } @end diff --git a/QueryKit/ObjectiveC/QKQuerySet.m b/QueryKit/ObjectiveC/QKQuerySet.m index 329f19b..0d28557 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.m +++ b/QueryKit/ObjectiveC/QKQuerySet.m @@ -79,7 +79,7 @@ - (BOOL)isEqualToQuerySet:(QKQuerySet *)queryset { [self.predicate isEqual:[queryset predicate]] && [self.sortDescriptors isEqual:[queryset sortDescriptors]] && NSEqualRanges(self.range, queryset.range) - ); + ); } #pragma mark - NSCopying @@ -260,9 +260,8 @@ - (NSManagedObject *)object:(NSError **)error { if (count == 1) { managedObject = [array firstObject]; } else if ((count > 1) && error != nil) { - *error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{ - NSLocalizedDescriptionKey: @"Find object in fetch request failed, should only result in a single result.", - }]; + NSString *errorDescription = @"Find object in fetch request failed, should only result in a single result."; + *error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: errorDescription }]; } return managedObject; From 02d56654e5e2caea5ac8fa7c4010996c07e52aa7 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 20 Sep 2015 12:16:06 -0700 Subject: [PATCH 43/71] [Objective-C] Remove parameter asserts We expose nullability in the headers --- QueryKit/ObjectiveC/QKAttribute.m | 9 --------- QueryKit/ObjectiveC/QKQuerySet.m | 5 ----- 2 files changed, 14 deletions(-) diff --git a/QueryKit/ObjectiveC/QKAttribute.m b/QueryKit/ObjectiveC/QKAttribute.m index dd90e2e..c16a99e 100644 --- a/QueryKit/ObjectiveC/QKAttribute.m +++ b/QueryKit/ObjectiveC/QKAttribute.m @@ -35,8 +35,6 @@ - (instancetype)copyWithZone:(NSZone *)zone { #pragma mark - - (instancetype)initWithAttributes:(QKAttribute *)attribute, ... { - NSParameterAssert(attribute != nil); - NSMutableArray *attributes = [NSMutableArray arrayWithObject:attribute.name]; va_list attributeList; @@ -192,23 +190,16 @@ - (NSPredicate *)isNil { } - (NSPredicate *)between:(id)minimumValue and:(id)maxiumValue { - NSParameterAssert(minimumValue != nil); - NSParameterAssert(maxiumValue != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:@[minimumValue, maxiumValue]]; return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSBetweenPredicateOperatorType options:0]; } - (NSPredicate *)in:(id)set { - NSParameterAssert(set != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:set]; return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0]; } - (NSPredicate *)contains:(id)value options:(NSComparisonPredicateOptions)options { - NSParameterAssert(value != nil); - NSExpression *expression = [NSExpression expressionForConstantValue:value]; return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSContainsPredicateOperatorType options:options]; } diff --git a/QueryKit/ObjectiveC/QKQuerySet.m b/QueryKit/ObjectiveC/QKQuerySet.m index 0d28557..aaf4ced 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.m +++ b/QueryKit/ObjectiveC/QKQuerySet.m @@ -25,8 +25,6 @@ - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedOb } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest { - NSParameterAssert(fetchRequest != nil); - NSEntityDescription *entityDescription = [fetchRequest entity]; NSPredicate *predicate = [fetchRequest predicate]; NSArray *sortDescriptors = [fetchRequest sortDescriptors]; @@ -35,9 +33,6 @@ - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedOb } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription predicate:(NSPredicate *)predicate sortDescriptors:(NSArray *)sortDescriptors range:(NSRange)range { - NSParameterAssert(managedObjectContext != nil); - NSParameterAssert(entityDescription != nil); - if (self = [super init]) { _managedObjectContext = managedObjectContext; _entityDescription = entityDescription; From 94d3731f4e4f1ff66f45ea3501dc3cf5d9775e82 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 20 Sep 2015 12:35:48 -0700 Subject: [PATCH 44/71] [Objective-C] Go on a diet --- QueryKit/ObjectiveC/QKAttribute.m | 8 ----- QueryKit/ObjectiveC/QKQuerySet.m | 50 +++++-------------------------- 2 files changed, 7 insertions(+), 51 deletions(-) diff --git a/QueryKit/ObjectiveC/QKAttribute.m b/QueryKit/ObjectiveC/QKAttribute.m index c16a99e..b0999e6 100644 --- a/QueryKit/ObjectiveC/QKAttribute.m +++ b/QueryKit/ObjectiveC/QKAttribute.m @@ -1,11 +1,3 @@ -// -// QKAttribute.m -// QueryKit -// -// Created by Kyle Fuller on 30/04/2013. -// -// - #import "QKAttribute.h" @implementation QKAttribute diff --git a/QueryKit/ObjectiveC/QKQuerySet.m b/QueryKit/ObjectiveC/QKQuerySet.m index aaf4ced..23ec919 100644 --- a/QueryKit/ObjectiveC/QKQuerySet.m +++ b/QueryKit/ObjectiveC/QKQuerySet.m @@ -1,11 +1,3 @@ -// -// QKQuerySet.m -// QueryKit -// -// Created by Kyle Fuller on 30/04/2013. -// -// - #import "QKQuerySet.h" NSString * const QKQuerySetErrorDomain = @"QKQuerySetErrorDomain"; @@ -25,11 +17,7 @@ - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedOb } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest { - NSEntityDescription *entityDescription = [fetchRequest entity]; - NSPredicate *predicate = [fetchRequest predicate]; - NSArray *sortDescriptors = [fetchRequest sortDescriptors]; - - return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)]; + return [self initWithManagedObjectContext:managedObjectContext entityDescription:fetchRequest.entity predicate:fetchRequest.predicate sortDescriptors:fetchRequest.sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)]; } - (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription predicate:(NSPredicate *)predicate sortDescriptors:(NSArray *)sortDescriptors range:(NSRange)range { @@ -56,25 +44,11 @@ - (NSUInteger)hash { } - (BOOL)isEqual:(id)object { - if (self == object) { - return YES; - } - - if ([object isKindOfClass:[QKQuerySet class]] == NO) { - return NO; - } - - return [self isEqualToQuerySet:object]; + return (self == object) || ([object isKindOfClass:[QKQuerySet class]] && [self isEqualToQuerySet:object]); } - (BOOL)isEqualToQuerySet:(QKQuerySet *)queryset { - return ( - [self.managedObjectContext isEqual:[queryset managedObjectContext]] && - [self.entityDescription isEqual:[queryset entityDescription]] && - [self.predicate isEqual:[queryset predicate]] && - [self.sortDescriptors isEqual:[queryset sortDescriptors]] && - NSEqualRanges(self.range, queryset.range) - ); + return [self.managedObjectContext isEqual:[queryset managedObjectContext]] && [self.entityDescription isEqual:[queryset entityDescription]] && [self.predicate isEqual:[queryset predicate]] && [self.sortDescriptors isEqual:[queryset sortDescriptors]] && NSEqualRanges(self.range, queryset.range); } #pragma mark - NSCopying @@ -86,11 +60,7 @@ - (instancetype)copyWithZone:(NSZone *)zone { #pragma mark - NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { - if (_resultsCache == nil) { - [self array:nil]; - } - - return [_resultsCache countByEnumeratingWithState:state objects:buffer count:len]; + return [[self array:nil] countByEnumeratingWithState:state objects:buffer count:len]; } #pragma mark - Fetching @@ -163,15 +133,9 @@ - (BOOL)enumerateObjects:(void (^)(NSManagedObject *object, NSUInteger index, BO } - (BOOL)each:(void (^)(NSManagedObject *managedObject))block error:(NSError **)error { - NSArray *array = [self array:error]; - - if (array != nil) { - for (NSManagedObject *managedObject in array) { - block(managedObject); - } - } - - return array != nil; + return [self enumerateObjects:^(NSManagedObject * _Nonnull object, NSUInteger index, BOOL * _Nonnull stop) { + block(object); + } error:error]; } #pragma mark - Deletion From 4304a76f90c47faed53b9891c710a5182605ed10 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 20 Sep 2015 15:54:12 -0700 Subject: [PATCH 45/71] [travis] Disable watchOS building --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ac7b12..e0071d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,5 @@ script: - set -o pipefail - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c - - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit build -sdk watchos | xcpretty -c - - pod lib lint --allow-warnings + - pod lib lint --allow-warnings --quick From 4126c96a7c364e6c4edb6b2f4961e93339997f84 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 20 Oct 2015 10:27:48 -0700 Subject: [PATCH 46/71] Add test case around comparing attributes to nil --- QueryKitTests/AttributeTests.swift | 6 ++++++ QueryKitTests/PredicateTests.swift | 6 ++++++ QueryKitTests/QuerySetTests.swift | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/QueryKitTests/AttributeTests.swift b/QueryKitTests/AttributeTests.swift index 65498a2..e411fac 100644 --- a/QueryKitTests/AttributeTests.swift +++ b/QueryKitTests/AttributeTests.swift @@ -104,6 +104,12 @@ class AttributeTests: XCTestCase { let predicate:NSPredicate = (attribute == "kyle") XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")) } + + func testEqualityOperatorWithNilRHS() { + let attribute = Attribute("name") + let predicate: NSPredicate = attribute == nil + XCTAssertEqual(predicate.description, "name == ") + } } class CollectionAttributeTests: XCTestCase { diff --git a/QueryKitTests/PredicateTests.swift b/QueryKitTests/PredicateTests.swift index 5f93c8b..1746ecf 100644 --- a/QueryKitTests/PredicateTests.swift +++ b/QueryKitTests/PredicateTests.swift @@ -46,6 +46,12 @@ class PredicateTests: XCTestCase { XCTAssertEqual(predicate.predicate, NSPredicate(format:"age == 10")) } + func testEqualityOperatorWithNilRHS() { + let attribute = Attribute("name") + let predicate: Predicate = attribute == nil + XCTAssertEqual(predicate.predicate.description, "name == ") + } + func testInequalityOperator() { let predicate:Predicate = (attribute != 10) XCTAssertEqual(predicate.predicate, NSPredicate(format:"age != 10")) diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 69f322b..7ce5c79 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -105,6 +105,11 @@ class QuerySetTests: XCTestCase { XCTAssertEqual(qs.predicate?.description, "name == \"Kyle\"") } + func testTypeSafeFilerEqualWithNilRHS() { + let qs = queryset.filter { $0.name == nil } + XCTAssertEqual(qs.predicate?.description, "name == ") + } + func testTypeSafeRelatedFilterPredicate() { let at = Attribute("company") XCTAssertEqual(at.name.key, "company.name") From f3052a770aa1537edb7e4a3452e217e9ea224c0e Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 3 Nov 2015 14:53:55 -0800 Subject: [PATCH 47/71] Prevent build warning --- QueryKitTests/QuerySetTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKitTests/QuerySetTests.swift b/QueryKitTests/QuerySetTests.swift index 7ce5c79..d1dbc3b 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/QueryKitTests/QuerySetTests.swift @@ -29,7 +29,7 @@ class QuerySetTests: XCTestCase { person.name = name if name == "Kyle" { - person.company == "Cocode" + person.company = company } } From 6cf07e8beb623e3f51493f2789e8bf8badbb44eb Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 3 Nov 2015 14:54:06 -0800 Subject: [PATCH 48/71] Update Configurations Closes #42 --- Configurations/LICENSE | 22 +++++++++++++++++++ .../UniversalFramework_Base.xcconfig | 20 ++++++++++------- .../UniversalFramework_Framework.xcconfig | 12 ++++++++++ .../UniversalFramework_Test.xcconfig | 12 +++++----- 4 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 Configurations/LICENSE diff --git a/Configurations/LICENSE b/Configurations/LICENSE new file mode 100644 index 0000000..ad21101 --- /dev/null +++ b/Configurations/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Marius Rackwitz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/Configurations/UniversalFramework_Base.xcconfig b/Configurations/UniversalFramework_Base.xcconfig index a82fa66..261e2b2 100644 --- a/Configurations/UniversalFramework_Base.xcconfig +++ b/Configurations/UniversalFramework_Base.xcconfig @@ -6,16 +6,20 @@ // // Make it universal -SUPPORTED_PLATFORMS = macosx iphonesimulator iphoneos watchos watchsimulator +SUPPORTED_PLATFORMS = macosx iphonesimulator iphoneos watchos watchsimulator appletvos appletvsimulator VALID_ARCHS[sdk=macosx*] = i386 x86_64 VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s -VALID_ARCHS[sdk=iphonesimulator*] = arm64 armv7 armv7s +VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 VALID_ARCHS[sdk=watchos*] = armv7k -VALID_ARCHS[sdk=watchsimulator*] = armv7k +VALID_ARCHS[sdk=watchsimulator*] = i386 +VALID_ARCHS[sdk=appletv*] = arm64 +VALID_ARCHS[sdk=appletvsimulator*] = x86_64 // Dynamic linking uses different default copy paths -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/Configurations/UniversalFramework_Framework.xcconfig b/Configurations/UniversalFramework_Framework.xcconfig index c0c1f68..1406c7a 100644 --- a/Configurations/UniversalFramework_Framework.xcconfig +++ b/Configurations/UniversalFramework_Framework.xcconfig @@ -15,6 +15,18 @@ CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*] = 1,2 TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2 +// TV-specific default settings +TARGETED_DEVICE_FAMILY[sdk=appletvsimulator*] = 3 +TARGETED_DEVICE_FAMILY[sdk=appletv*] = 3 + // Watch-specific default settings TARGETED_DEVICE_FAMILY[sdk=watchsimulator*] = 4 TARGETED_DEVICE_FAMILY[sdk=watch*] = 4 + +ENABLE_BITCODE[sdk=macosx*] = NO +ENABLE_BITCODE[sdk=watchsimulator*] = YES +ENABLE_BITCODE[sdk=watch*] = YES +ENABLE_BITCODE[sdk=iphonesimulator*] = YES +ENABLE_BITCODE[sdk=iphone*] = YES +ENABLE_BITCODE[sdk=appletvsimulator*] = YES +ENABLE_BITCODE[sdk=appletv*] = YES diff --git a/Configurations/UniversalFramework_Test.xcconfig b/Configurations/UniversalFramework_Test.xcconfig index d225d11..0c5f845 100644 --- a/Configurations/UniversalFramework_Test.xcconfig +++ b/Configurations/UniversalFramework_Test.xcconfig @@ -9,8 +9,10 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) '$(PLATFORM_DIR)/Developer/Library/Frameworks' // Yep. -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' From 9147abcf7f2563c8355c21378cc5067c730b26e2 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 07:51:35 -0800 Subject: [PATCH 49/71] Don't include framework header in podspec Closes #45 Closes #46 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 13473d9..b8600d0 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -14,7 +14,7 @@ Pod::Spec.new do |spec| spec.frameworks = 'CoreData' spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.source_files = 'QueryKit/QueryKit.h', 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' + objc_spec.source_files = 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' end spec.subspec 'Swift' do |swift_spec| From e48406968e1cb7e6a4af7bb247984451b4eb9f3b Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 07:53:17 -0800 Subject: [PATCH 50/71] Release 0.11.1 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index b8600d0..399b131 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.0' + spec.version = '0.11.1' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 70fd3952802ff253c20c92e83e2f71fabe28fda4 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 08:22:06 -0800 Subject: [PATCH 51/71] Remove Objective-C compatibility layer --- .travis.yml | 6 +- QueryKit.podspec | 15 +- QueryKit.xcodeproj/project.pbxproj | 516 ++++++------------ .../xcshareddata/xcschemes/QueryKit.xcscheme | 20 +- QueryKit/Info.plist | 8 +- QueryKit/ObjectiveC/QKAttribute.h | 213 -------- QueryKit/ObjectiveC/QKAttribute.m | 225 -------- QueryKit/ObjectiveC/QKAttribute.swift | 13 - QueryKit/ObjectiveC/QKQuerySet.h | 157 ------ QueryKit/ObjectiveC/QKQuerySet.m | 272 --------- QueryKit/ObjectiveC/QKQuerySet.swift | 34 -- QueryKit/QueryKit.h | 6 +- QueryKitTests/Info.plist | 4 +- .../ObjectiveC/QKAttributeTests.swift | 85 --- QueryKitTests/ObjectiveC/QKQuerySetTests.m | 141 ----- .../ObjectiveC/QKQuerySetTests.swift | 37 -- .../QueryKitTests-Bridging-Header.h | 4 - QueryKitTests/Person.h | 15 - 18 files changed, 184 insertions(+), 1587 deletions(-) delete mode 100644 QueryKit/ObjectiveC/QKAttribute.h delete mode 100644 QueryKit/ObjectiveC/QKAttribute.m delete mode 100644 QueryKit/ObjectiveC/QKAttribute.swift delete mode 100644 QueryKit/ObjectiveC/QKQuerySet.h delete mode 100644 QueryKit/ObjectiveC/QKQuerySet.m delete mode 100644 QueryKit/ObjectiveC/QKQuerySet.swift delete mode 100644 QueryKitTests/ObjectiveC/QKAttributeTests.swift delete mode 100644 QueryKitTests/ObjectiveC/QKQuerySetTests.m delete mode 100644 QueryKitTests/ObjectiveC/QKQuerySetTests.swift delete mode 100644 QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h delete mode 100644 QueryKitTests/Person.h diff --git a/.travis.yml b/.travis.yml index e0071d2..d1e7a88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,7 @@ language: objective-c -osx_image: xcode7 -before_install: - - gem install cocoapods --no-rdoc --no-ri --no-document --quiet - - gem install xcpretty --no-rdoc --no-ri --no-document --quiet +osx_image: xcode7.1 script: - set -o pipefail - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c - pod lib lint --allow-warnings --quick - diff --git a/QueryKit.podspec b/QueryKit.podspec index 399b131..7de46ae 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -12,19 +12,6 @@ Pod::Spec.new do |spec| spec.osx.deployment_target = '10.9' spec.watchos.deployment_target = '2.0' spec.frameworks = 'CoreData' - - spec.subspec 'ObjectiveC' do |objc_spec| - objc_spec.source_files = 'QueryKit/ObjectiveC/QK{QuerySet,Attribute}.{h,m}' - end - - spec.subspec 'Swift' do |swift_spec| - swift_spec.source_files = 'QueryKit/*.swift' - end - - spec.subspec 'Bridge' do |bridge_spec| - bridge_spec.dependency 'QueryKit/Swift' - bridge_spec.dependency 'QueryKit/ObjectiveC' - bridge_spec.source_files = 'QueryKit/ObjectiveC/QK{Attribute,QuerySet}.swift' - end + spec.source_files = 'QueryKit/*.swift' end diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index e769bea..17851a8 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -7,237 +7,136 @@ objects = { /* Begin PBXBuildFile section */ - 2794C8AD1B9F980100216C36 /* SortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */; settings = {ASSET_TAGS = (); }; }; - 2794C8AF1B9F985900216C36 /* SortDescriptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */; settings = {ASSET_TAGS = (); }; }; - 77007D7D19A95CDE007DC2BC /* QKQuerySetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77007D7C19A95CDE007DC2BC /* QKQuerySetTests.swift */; }; - 77007D8119A95CE9007DC2BC /* QKQuerySet.h in Headers */ = {isa = PBXBuildFile; fileRef = 77007D7E19A95CE9007DC2BC /* QKQuerySet.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 77007D8219A95CE9007DC2BC /* QKQuerySet.m in Sources */ = {isa = PBXBuildFile; fileRef = 77007D7F19A95CE9007DC2BC /* QKQuerySet.m */; }; - 77007D8319A95CE9007DC2BC /* QKQuerySet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77007D8019A95CE9007DC2BC /* QKQuerySet.swift */; }; - 775E2A1B19B4981E007FE5BA /* QKQuerySetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 775E2A1A19B4981E007FE5BA /* QKQuerySetTests.m */; }; - 77A9B67F195374490016654E /* QueryKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 77A9B67E195374490016654E /* QueryKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 77A9B685195374490016654E /* QueryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77A9B679195374490016654E /* QueryKit.framework */; }; - 77A9B68C195374490016654E /* QueryKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A9B68B195374490016654E /* QueryKitTests.swift */; }; - 77B17B8519A94C9100D6540D /* QKAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 77B17B8319A94C9100D6540D /* QKAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 77B17B8619A94C9100D6540D /* QKAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 77B17B8419A94C9100D6540D /* QKAttribute.m */; }; - 77B17B8819A94D2C00D6540D /* QKAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B17B8719A94D2C00D6540D /* QKAttribute.swift */; }; - 77B17B8B19A94D4C00D6540D /* QKAttributeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77B17B8A19A94D4C00D6540D /* QKAttributeTests.swift */; }; - 77E3A05D1969C019009372A8 /* QuerySet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E3A05C1969C019009372A8 /* QuerySet.swift */; }; - 77E3A05F1969C047009372A8 /* QuerySetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E3A05E1969C047009372A8 /* QuerySetTests.swift */; }; - 77E3A0611969DDF5009372A8 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E3A0601969DDF5009372A8 /* Expression.swift */; }; - 77E3A0631969E003009372A8 /* ExpressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E3A0621969E003009372A8 /* ExpressionTests.swift */; }; - 77E8728119539C0900A6F13F /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E8728019539C0900A6F13F /* Attribute.swift */; }; - 77E8728319539C2A00A6F13F /* AttributeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E8728219539C2A00A6F13F /* AttributeTests.swift */; }; - 77E8728519539FC000A6F13F /* PredicateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E8728419539FC000A6F13F /* PredicateTests.swift */; }; - 77E8728719539FD200A6F13F /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77E8728619539FD200A6F13F /* Predicate.swift */; }; + 279ED5841BED09EB0011CA09 /* QueryKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 279ED5831BED09EB0011CA09 /* QueryKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 279ED58B1BED09EB0011CA09 /* QueryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279ED5801BED09EB0011CA09 /* QueryKit.framework */; }; + 279ED5901BED09EB0011CA09 /* QueryKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */; }; + 279ED59F1BED0A5C0011CA09 /* SortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */; }; + 279ED5A01BED0A5C0011CA09 /* QuerySet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */; }; + 279ED5A11BED0A5C0011CA09 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59C1BED0A5C0011CA09 /* Predicate.swift */; }; + 279ED5A21BED0A5C0011CA09 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59D1BED0A5C0011CA09 /* Expression.swift */; }; + 279ED5A31BED0A5C0011CA09 /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59E1BED0A5C0011CA09 /* Attribute.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 772A282A196C8D7800992BAB /* PBXContainerItemProxy */ = { + 279ED58C1BED09EB0011CA09 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 77A9B66E1953742F0016654E /* Project object */; + containerPortal = 279ED5771BED09EB0011CA09 /* Project object */; proxyType = 1; - remoteGlobalIDString = 77A9B678195374490016654E; - remoteInfo = QueryKit; - }; - 77A9B686195374490016654E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 77A9B66E1953742F0016654E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 77A9B678195374490016654E; - remoteInfo = QueryKit; - }; - 77A9B6931953744A0016654E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 77A9B66E1953742F0016654E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 77A9B678195374490016654E; - remoteInfo = QueryKit; - }; - 77A9B6951953744A0016654E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 77A9B66E1953742F0016654E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 77A9B678195374490016654E; + remoteGlobalIDString = 279ED57F1BED09EB0011CA09; remoteInfo = QueryKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 279294E51A4B4C60009C52E1 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; - 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; - 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; - 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptor.swift; sourceTree = ""; }; - 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptorTests.swift; sourceTree = ""; }; - 77007D7C19A95CDE007DC2BC /* QKQuerySetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKQuerySetTests.swift; sourceTree = ""; }; - 77007D7E19A95CE9007DC2BC /* QKQuerySet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QKQuerySet.h; sourceTree = ""; }; - 77007D7F19A95CE9007DC2BC /* QKQuerySet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKQuerySet.m; sourceTree = ""; }; - 77007D8019A95CE9007DC2BC /* QKQuerySet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKQuerySet.swift; sourceTree = ""; }; - 775E2A1919B4981D007FE5BA /* QueryKitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QueryKitTests-Bridging-Header.h"; sourceTree = ""; }; - 775E2A1A19B4981E007FE5BA /* QKQuerySetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKQuerySetTests.m; sourceTree = ""; }; - 77A9B679195374490016654E /* QueryKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = QueryKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 77A9B67D195374490016654E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 77A9B67E195374490016654E /* QueryKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QueryKit.h; sourceTree = ""; }; - 77A9B684195374490016654E /* QueryKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QueryKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 77A9B68A195374490016654E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 77A9B68B195374490016654E /* QueryKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryKitTests.swift; sourceTree = ""; }; - 77B17B8319A94C9100D6540D /* QKAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QKAttribute.h; sourceTree = ""; }; - 77B17B8419A94C9100D6540D /* QKAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QKAttribute.m; sourceTree = ""; }; - 77B17B8719A94D2C00D6540D /* QKAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKAttribute.swift; sourceTree = ""; }; - 77B17B8A19A94D4C00D6540D /* QKAttributeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QKAttributeTests.swift; sourceTree = ""; }; - 77E3A05C1969C019009372A8 /* QuerySet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuerySet.swift; sourceTree = ""; }; - 77E3A05E1969C047009372A8 /* QuerySetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuerySetTests.swift; sourceTree = ""; }; - 77E3A0601969DDF5009372A8 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; - 77E3A0621969E003009372A8 /* ExpressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpressionTests.swift; sourceTree = ""; }; - 77E8728019539C0900A6F13F /* Attribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attribute.swift; sourceTree = ""; }; - 77E8728219539C2A00A6F13F /* AttributeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributeTests.swift; sourceTree = ""; }; - 77E8728419539FC000A6F13F /* PredicateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredicateTests.swift; sourceTree = ""; }; - 77E8728619539FD200A6F13F /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 279ED5801BED09EB0011CA09 /* QueryKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = QueryKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 279ED5831BED09EB0011CA09 /* QueryKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QueryKit.h; sourceTree = ""; }; + 279ED5851BED09EB0011CA09 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QueryKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryKitTests.swift; sourceTree = ""; }; + 279ED5911BED09EB0011CA09 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptor.swift; sourceTree = ""; }; + 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuerySet.swift; sourceTree = ""; }; + 279ED59C1BED0A5C0011CA09 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; + 279ED59D1BED0A5C0011CA09 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; + 279ED59E1BED0A5C0011CA09 /* Attribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attribute.swift; sourceTree = ""; }; + 279ED5A61BED0AA50011CA09 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; + 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; + 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 77A9B675195374490016654E /* Frameworks */ = { + 279ED57C1BED09EB0011CA09 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 77A9B681195374490016654E /* Frameworks */ = { + 279ED5871BED09EB0011CA09 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 77A9B685195374490016654E /* QueryKit.framework in Frameworks */, + 279ED58B1BED09EB0011CA09 /* QueryKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 279294E41A4B4C60009C52E1 /* Configurations */ = { - isa = PBXGroup; - children = ( - 279294E51A4B4C60009C52E1 /* UniversalFramework_Base.xcconfig */, - 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */, - 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */, - ); - path = Configurations; - sourceTree = ""; - }; - 77A9B66D1953742F0016654E = { + 279ED5761BED09EB0011CA09 = { isa = PBXGroup; children = ( - 77A9B67B195374490016654E /* QueryKit */, - 77A9B688195374490016654E /* QueryKitTests */, - 279294E41A4B4C60009C52E1 /* Configurations */, - 77A9B67A195374490016654E /* Products */, + 279ED5A41BED0AA50011CA09 /* Configurations */, + 279ED5821BED09EB0011CA09 /* QueryKit */, + 279ED58E1BED09EB0011CA09 /* QueryKitTests */, + 279ED5811BED09EB0011CA09 /* Products */, ); - indentWidth = 2; sourceTree = ""; - tabWidth = 2; }; - 77A9B67A195374490016654E /* Products */ = { + 279ED5811BED09EB0011CA09 /* Products */ = { isa = PBXGroup; children = ( - 77A9B679195374490016654E /* QueryKit.framework */, - 77A9B684195374490016654E /* QueryKitTests.xctest */, + 279ED5801BED09EB0011CA09 /* QueryKit.framework */, + 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */, ); name = Products; sourceTree = ""; }; - 77A9B67B195374490016654E /* QueryKit */ = { + 279ED5821BED09EB0011CA09 /* QueryKit */ = { isa = PBXGroup; children = ( - 77A9B67E195374490016654E /* QueryKit.h */, - 77E3A05C1969C019009372A8 /* QuerySet.swift */, - 77E8728019539C0900A6F13F /* Attribute.swift */, - 77E3A0601969DDF5009372A8 /* Expression.swift */, - 77E8728619539FD200A6F13F /* Predicate.swift */, - 2794C8AC1B9F980100216C36 /* SortDescriptor.swift */, - 77B17B8219A94C9100D6540D /* ObjectiveC */, - 77A9B67C195374490016654E /* Supporting Files */, + 279ED5831BED09EB0011CA09 /* QueryKit.h */, + 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */, + 279ED59E1BED0A5C0011CA09 /* Attribute.swift */, + 279ED59D1BED0A5C0011CA09 /* Expression.swift */, + 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */, + 279ED59C1BED0A5C0011CA09 /* Predicate.swift */, + 279ED5851BED09EB0011CA09 /* Info.plist */, ); path = QueryKit; sourceTree = ""; }; - 77A9B67C195374490016654E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 77A9B67D195374490016654E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 77A9B688195374490016654E /* QueryKitTests */ = { + 279ED58E1BED09EB0011CA09 /* QueryKitTests */ = { isa = PBXGroup; children = ( - 77A9B68B195374490016654E /* QueryKitTests.swift */, - 77E3A05E1969C047009372A8 /* QuerySetTests.swift */, - 77E3A0621969E003009372A8 /* ExpressionTests.swift */, - 77E8728219539C2A00A6F13F /* AttributeTests.swift */, - 77E8728419539FC000A6F13F /* PredicateTests.swift */, - 2794C8AE1B9F985900216C36 /* SortDescriptorTests.swift */, - 77B17B8919A94D4C00D6540D /* ObjectiveC */, - 77A9B689195374490016654E /* Supporting Files */, + 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */, + 279ED5911BED09EB0011CA09 /* Info.plist */, ); path = QueryKitTests; sourceTree = ""; }; - 77A9B689195374490016654E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 77A9B68A195374490016654E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 77B17B8219A94C9100D6540D /* ObjectiveC */ = { - isa = PBXGroup; - children = ( - 77B17B8319A94C9100D6540D /* QKAttribute.h */, - 77B17B8419A94C9100D6540D /* QKAttribute.m */, - 77B17B8719A94D2C00D6540D /* QKAttribute.swift */, - 77007D7E19A95CE9007DC2BC /* QKQuerySet.h */, - 77007D7F19A95CE9007DC2BC /* QKQuerySet.m */, - 77007D8019A95CE9007DC2BC /* QKQuerySet.swift */, - ); - path = ObjectiveC; - sourceTree = ""; - }; - 77B17B8919A94D4C00D6540D /* ObjectiveC */ = { + 279ED5A41BED0AA50011CA09 /* Configurations */ = { isa = PBXGroup; children = ( - 775E2A1919B4981D007FE5BA /* QueryKitTests-Bridging-Header.h */, - 77B17B8A19A94D4C00D6540D /* QKAttributeTests.swift */, - 775E2A1A19B4981E007FE5BA /* QKQuerySetTests.m */, - 77007D7C19A95CDE007DC2BC /* QKQuerySetTests.swift */, + 279ED5A61BED0AA50011CA09 /* UniversalFramework_Base.xcconfig */, + 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */, + 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */, ); - path = ObjectiveC; + path = Configurations; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 77A9B676195374490016654E /* Headers */ = { + 279ED57D1BED09EB0011CA09 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 77A9B67F195374490016654E /* QueryKit.h in Headers */, - 77B17B8519A94C9100D6540D /* QKAttribute.h in Headers */, - 77007D8119A95CE9007DC2BC /* QKQuerySet.h in Headers */, + 279ED5841BED09EB0011CA09 /* QueryKit.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 77A9B678195374490016654E /* QueryKit */ = { + 279ED57F1BED09EB0011CA09 /* QueryKit */ = { isa = PBXNativeTarget; - buildConfigurationList = 77A9B68D195374490016654E /* Build configuration list for PBXNativeTarget "QueryKit" */; + buildConfigurationList = 279ED5941BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKit" */; buildPhases = ( - 77A9B674195374490016654E /* Sources */, - 77A9B675195374490016654E /* Frameworks */, - 77A9B676195374490016654E /* Headers */, - 77A9B677195374490016654E /* Resources */, + 279ED57B1BED09EB0011CA09 /* Sources */, + 279ED57C1BED09EB0011CA09 /* Frameworks */, + 279ED57D1BED09EB0011CA09 /* Headers */, + 279ED57E1BED09EB0011CA09 /* Resources */, ); buildRules = ( ); @@ -245,75 +144,72 @@ ); name = QueryKit; productName = QueryKit; - productReference = 77A9B679195374490016654E /* QueryKit.framework */; + productReference = 279ED5801BED09EB0011CA09 /* QueryKit.framework */; productType = "com.apple.product-type.framework"; }; - 77A9B683195374490016654E /* QueryKitTests */ = { + 279ED5891BED09EB0011CA09 /* QueryKitTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 77A9B690195374490016654E /* Build configuration list for PBXNativeTarget "QueryKitTests" */; + buildConfigurationList = 279ED5971BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKitTests" */; buildPhases = ( - 77A9B680195374490016654E /* Sources */, - 77A9B681195374490016654E /* Frameworks */, - 77A9B682195374490016654E /* Resources */, + 279ED5861BED09EB0011CA09 /* Sources */, + 279ED5871BED09EB0011CA09 /* Frameworks */, + 279ED5881BED09EB0011CA09 /* Resources */, ); buildRules = ( ); dependencies = ( - 77A9B687195374490016654E /* PBXTargetDependency */, - 77A9B6941953744A0016654E /* PBXTargetDependency */, - 77A9B6961953744A0016654E /* PBXTargetDependency */, - 772A282B196C8D7800992BAB /* PBXTargetDependency */, + 279ED58D1BED09EB0011CA09 /* PBXTargetDependency */, ); name = QueryKitTests; productName = QueryKitTests; - productReference = 77A9B684195374490016654E /* QueryKitTests.xctest */; + productReference = 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 77A9B66E1953742F0016654E /* Project object */ = { + 279ED5771BED09EB0011CA09 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; + LastSwiftUpdateCheck = 0710; + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = QueryKit; TargetAttributes = { - 77A9B678195374490016654E = { - CreatedOnToolsVersion = 6.0; + 279ED57F1BED09EB0011CA09 = { + CreatedOnToolsVersion = 7.1; }; - 77A9B683195374490016654E = { - CreatedOnToolsVersion = 6.0; - TestTargetID = 77A9B678195374490016654E; + 279ED5891BED09EB0011CA09 = { + CreatedOnToolsVersion = 7.1; }; }; }; - buildConfigurationList = 77A9B6711953742F0016654E /* Build configuration list for PBXProject "QueryKit" */; + buildConfigurationList = 279ED57A1BED09EB0011CA09 /* Build configuration list for PBXProject "QueryKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); - mainGroup = 77A9B66D1953742F0016654E; - productRefGroup = 77A9B67A195374490016654E /* Products */; + mainGroup = 279ED5761BED09EB0011CA09; + productRefGroup = 279ED5811BED09EB0011CA09 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 77A9B678195374490016654E /* QueryKit */, - 77A9B683195374490016654E /* QueryKitTests */, + 279ED57F1BED09EB0011CA09 /* QueryKit */, + 279ED5891BED09EB0011CA09 /* QueryKitTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 77A9B677195374490016654E /* Resources */ = { + 279ED57E1BED09EB0011CA09 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 77A9B682195374490016654E /* Resources */ = { + 279ED5881BED09EB0011CA09 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -323,83 +219,39 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 77A9B674195374490016654E /* Sources */ = { + 279ED57B1BED09EB0011CA09 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 77E8728119539C0900A6F13F /* Attribute.swift in Sources */, - 77E8728719539FD200A6F13F /* Predicate.swift in Sources */, - 77B17B8619A94C9100D6540D /* QKAttribute.m in Sources */, - 77B17B8819A94D2C00D6540D /* QKAttribute.swift in Sources */, - 77007D8319A95CE9007DC2BC /* QKQuerySet.swift in Sources */, - 2794C8AD1B9F980100216C36 /* SortDescriptor.swift in Sources */, - 77007D8219A95CE9007DC2BC /* QKQuerySet.m in Sources */, - 77E3A05D1969C019009372A8 /* QuerySet.swift in Sources */, - 77E3A0611969DDF5009372A8 /* Expression.swift in Sources */, + 279ED5A31BED0A5C0011CA09 /* Attribute.swift in Sources */, + 279ED59F1BED0A5C0011CA09 /* SortDescriptor.swift in Sources */, + 279ED5A11BED0A5C0011CA09 /* Predicate.swift in Sources */, + 279ED5A01BED0A5C0011CA09 /* QuerySet.swift in Sources */, + 279ED5A21BED0A5C0011CA09 /* Expression.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 77A9B680195374490016654E /* Sources */ = { + 279ED5861BED09EB0011CA09 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 77B17B8B19A94D4C00D6540D /* QKAttributeTests.swift in Sources */, - 77E8728319539C2A00A6F13F /* AttributeTests.swift in Sources */, - 2794C8AF1B9F985900216C36 /* SortDescriptorTests.swift in Sources */, - 77A9B68C195374490016654E /* QueryKitTests.swift in Sources */, - 77007D7D19A95CDE007DC2BC /* QKQuerySetTests.swift in Sources */, - 77E3A05F1969C047009372A8 /* QuerySetTests.swift in Sources */, - 775E2A1B19B4981E007FE5BA /* QKQuerySetTests.m in Sources */, - 77E8728519539FC000A6F13F /* PredicateTests.swift in Sources */, - 77E3A0631969E003009372A8 /* ExpressionTests.swift in Sources */, + 279ED5901BED09EB0011CA09 /* QueryKitTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 772A282B196C8D7800992BAB /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 77A9B678195374490016654E /* QueryKit */; - targetProxy = 772A282A196C8D7800992BAB /* PBXContainerItemProxy */; - }; - 77A9B687195374490016654E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 77A9B678195374490016654E /* QueryKit */; - targetProxy = 77A9B686195374490016654E /* PBXContainerItemProxy */; - }; - 77A9B6941953744A0016654E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 77A9B678195374490016654E /* QueryKit */; - targetProxy = 77A9B6931953744A0016654E /* PBXContainerItemProxy */; - }; - 77A9B6961953744A0016654E /* PBXTargetDependency */ = { + 279ED58D1BED09EB0011CA09 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 77A9B678195374490016654E /* QueryKit */; - targetProxy = 77A9B6951953744A0016654E /* PBXContainerItemProxy */; + target = 279ED57F1BED09EB0011CA09 /* QueryKit */; + targetProxy = 279ED58C1BED09EB0011CA09 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 77A9B6721953742F0016654E /* Debug */ = { + 279ED5921BED09EB0011CA09 /* Debug */ = { isa = XCBuildConfiguration; - buildSettings = { - ENABLE_TESTABILITY = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - ONLY_ACTIVE_ARCH = YES; - }; - name = Debug; - }; - 77A9B6731953742F0016654E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - MACOSX_DEPLOYMENT_TARGET = 10.9; - }; - name = Release; - }; - 77A9B68E195374490016654E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -415,47 +267,38 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; + CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_VERSION = A; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = QueryKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - METAL_ENABLE_DEBUG_INFO = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 77A9B68F195374490016654E /* Release */ = { + 279ED5931BED09EB0011CA09 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -471,155 +314,124 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_VERSION = A; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = QueryKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - METAL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME)"; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; - SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 77A9B691195374490016654E /* Debug */ = { + 279ED5951BED09EB0011CA09 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 279294E71A4B4C60009C52E1 /* UniversalFramework_Test.xcconfig */; + baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = QueryKitTests/Info.plist; - MACOSX_DEPLOYMENT_TARGET = 10.10; - METAL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = QueryKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SWIFT_OBJC_BRIDGING_HEADER = "QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h"; + SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; - 77A9B692195374490016654E /* Release */ = { + 279ED5961BED09EB0011CA09 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 279294E61A4B4C60009C52E1 /* UniversalFramework_Framework.xcconfig */; + baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = QueryKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 279ED5981BED09EB0011CA09 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = QueryKitTests/Info.plist; - MACOSX_DEPLOYMENT_TARGET = 10.10; - METAL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.${PRODUCT_NAME:rfc1034identifier}"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 279ED5991BED09EB0011CA09 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = QueryKitTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SWIFT_OBJC_BRIDGING_HEADER = "QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 77A9B6711953742F0016654E /* Build configuration list for PBXProject "QueryKit" */ = { + 279ED57A1BED09EB0011CA09 /* Build configuration list for PBXProject "QueryKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 77A9B6721953742F0016654E /* Debug */, - 77A9B6731953742F0016654E /* Release */, + 279ED5921BED09EB0011CA09 /* Debug */, + 279ED5931BED09EB0011CA09 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 77A9B68D195374490016654E /* Build configuration list for PBXNativeTarget "QueryKit" */ = { + 279ED5941BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 77A9B68E195374490016654E /* Debug */, - 77A9B68F195374490016654E /* Release */, + 279ED5951BED09EB0011CA09 /* Debug */, + 279ED5961BED09EB0011CA09 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 77A9B690195374490016654E /* Build configuration list for PBXNativeTarget "QueryKitTests" */ = { + 279ED5971BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 77A9B691195374490016654E /* Debug */, - 77A9B692195374490016654E /* Release */, + 279ED5981BED09EB0011CA09 /* Debug */, + 279ED5991BED09EB0011CA09 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 77A9B66E1953742F0016654E /* Project object */; + rootObject = 279ED5771BED09EB0011CA09 /* Project object */; } diff --git a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme index 1aee5e5..d332541 100644 --- a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme +++ b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme @@ -1,6 +1,6 @@ @@ -23,16 +23,16 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -42,7 +42,7 @@ @@ -52,11 +52,11 @@ @@ -74,15 +74,15 @@ diff --git a/QueryKit/Info.plist b/QueryKit/Info.plist index 7812205..f2e8865 100644 --- a/QueryKit/Info.plist +++ b/QueryKit/Info.plist @@ -5,13 +5,13 @@ CFBundleDevelopmentRegion en CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString @@ -19,7 +19,9 @@ CFBundleSignature ???? CFBundleVersion - ${CURRENT_PROJECT_VERSION} + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 QueryKit. All rights reserved. NSPrincipalClass diff --git a/QueryKit/ObjectiveC/QKAttribute.h b/QueryKit/ObjectiveC/QKAttribute.h deleted file mode 100644 index 035dfc4..0000000 --- a/QueryKit/ObjectiveC/QKAttribute.h +++ /dev/null @@ -1,213 +0,0 @@ -// -// QKAttribute.h -// QueryKit -// -// Created by Kyle Fuller on 30/04/2013. -// -// - -#import - -/** A helper class to generate predicates and sort descriptors for attributes - on a managed object. - */ -@interface QKAttribute : NSObject - -/// The name for the attribute. -@property (nonatomic, strong, readonly, nonnull) NSString *name; - -/// Initialized the attribute from multiple other attributes -- (nonnull instancetype)initWithAttributes:(nonnull QKAttribute *)attribute, ... NS_REQUIRES_NIL_TERMINATION; - -/// Initialized the attribute with the given name -- (nonnull instancetype)initWithName:(nonnull NSString *)name; - -/** Returns a Boolean value that indicates whether a given attribute is equal to the receiver - @param attribute The attribute to compare against the receiver - @return YES if attribute is equivalent to the receiver - */ -- (BOOL)isEqualToAttribute:(nonnull QKAttribute *)attribute; - -/** Returns an expression for the attributes key-value path */ -- (nonnull NSExpression *)expression; - -@end - -/// Predicates -@interface QKAttribute (Predicate) - -/** Returns a predicate for an equality comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see equal: - */ -- (nonnull NSPredicate *)equal:(nullable id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for an equality comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see equal:options: - */ -- (nonnull NSPredicate *)equal:(nullable id)value; - -/** Returns a predicate for an unequal comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see notEqual: - */ -- (nonnull NSPredicate *)notEqual:(nullable id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for an unequal comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see notEqual:options: - */ -- (nonnull NSPredicate *)notEqual:(nullable id)value; - -/** Returns a predicate for a like comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see like: - */ -- (nonnull NSPredicate *)like:(nonnull id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for a like comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see like:options: - */ -- (nonnull NSPredicate *)like:(nonnull id)value; - -/** Returns a predicate for a matches comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see like: - */ -- (nonnull NSPredicate *)matches:(nonnull id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for a matches comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see like:options: - */ -- (nonnull NSPredicate *)matches:(nonnull id)value; - -/** Returns a predicate for a begins with comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see like: - */ -- (nonnull NSPredicate *)beginsWith:(nonnull id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for a begins with comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see like:options: - */ -- (nonnull NSPredicate *)beginsWith:(nonnull id)value; - -/** Returns a predicate for a ends with comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see like: - */ -- (nonnull NSPredicate *)endsWith:(nonnull id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for a ends with comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see like:options: - */ -- (nonnull NSPredicate *)endsWith:(nonnull id)value; - -/** Returns a predicate for greater than the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see greaterThanOrEqualTo: - */ -- (nonnull NSPredicate *)greaterThan:(nonnull id)value; - -/** Returns a predicate for greater than or equal to the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see greaterThan: - */ -- (nonnull NSPredicate *)greaterThanOrEqualTo:(nonnull id)value; - -/** Returns a predicate for less than the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see lessThanOrEqualTo: - */ -- (nonnull NSPredicate *)lessThan:(nonnull id)value; - -/** Returns a predicate for less than or equal to the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see lessThan: - */ -- (nonnull NSPredicate *)lessThanOrEqualTo:(nonnull id)value; - -/** Returns a predicate for attribute being between two values - @param minimumValue - @param maximumValue - @return The predicate for this comparison - */ -- (nonnull NSPredicate *)between:(nonnull id)minimumValue and:(nonnull id)maxiumValue; - -/** Returns an IN predicate for attribute - @param set An enumerable object containing a set ob objects - @return The predicate for this comparison - */ -- (nonnull NSPredicate *)in:(nonnull id)set; - -/** Returns a predicate for a contains with comparison against the supplied value - @param value To compare against the attribute - @param options NSComparisonPredicateOptions to apply to the comparison - @return The predicate for this comparison - @see contains: - */ -- (nonnull NSPredicate *)contains:(nonnull id)value options:(NSComparisonPredicateOptions)options; - -/** Returns a predicate for a contains with comparison against the supplied value - @param value To compare against the attribute - @return The predicate for this comparison - @see contains:options: - */ -- (nonnull NSPredicate *)contains:(nonnull id)value; - -/** Returns a predicate for if the attribute being equal to nil - @return The predicate for the attribute being nil. - */ -- (nonnull NSPredicate *)isNil; - -/** Returns a predicate for if the attribute being equal to YES - @return The predicate for the attribute being YES. - @see isNO - */ -- (nonnull NSPredicate *)isYes; - -/** Returns a predicate for if the attribute being equal to NO - @return The predicate for the attribute being NO. - @see isYes - */ -- (nonnull NSPredicate *)isNo; - -@end - -/// Sorting -@interface QKAttribute (Sorting) - -/** Returns an ascending sort descriptor for this attribute */ -- (nonnull NSSortDescriptor *)ascending; - -/** Returns a descending sort descriptor for this attribute */ -- (nonnull NSSortDescriptor *)descending; - -@end diff --git a/QueryKit/ObjectiveC/QKAttribute.m b/QueryKit/ObjectiveC/QKAttribute.m deleted file mode 100644 index b0999e6..0000000 --- a/QueryKit/ObjectiveC/QKAttribute.m +++ /dev/null @@ -1,225 +0,0 @@ -#import "QKAttribute.h" - -@implementation QKAttribute - -#pragma mark - NSCoding - -+ (BOOL)supportsSecureCoding { - return YES; -} - -- (void)encodeWithCoder:(NSCoder *)encoder { - [encoder encodeObject:self.name forKey:@"name"]; -} - -- (instancetype)initWithCoder:(NSCoder *)decoder { - NSString *name = [decoder decodeObjectOfClass:[NSString class] forKey:@"name"]; - return [self initWithName:name]; -} - -#pragma mark - NSCopying - -- (instancetype)copyWithZone:(NSZone *)zone { - NSString *name = [self.name copyWithZone:zone]; - return [[[self class] alloc] initWithName:name]; -} - -#pragma mark - - -- (instancetype)initWithAttributes:(QKAttribute *)attribute, ... { - NSMutableArray *attributes = [NSMutableArray arrayWithObject:attribute.name]; - - va_list attributeList; - va_start(attributeList, attribute); - while ((attribute = va_arg(attributeList, id))) { - [attributes addObject:attribute.name]; - } - va_end(attributeList); - - NSString *name = [attributes componentsJoinedByString:@"."]; - - if (self = [super init]) { - _name = name; - } - - return self; -} - -- (instancetype)initWithName:(NSString *)name { - if (self = [super init]) { - _name = name; - } - - return self; -} - -- (NSExpression *)expression { - return [NSExpression expressionForKeyPath:self.name]; -} - -#pragma mark - Equality - -- (NSUInteger)hash { - return [self.name hash]; -} - -- (BOOL)isEqualToAttribute:(QKAttribute *)attribute { - return [self.name isEqualToString:attribute.name]; -} - -- (BOOL)isEqual:(id)object { - return object == self || ([object isKindOfClass:[QKAttribute class]] && [self isEqualToAttribute:object]); -} - -#pragma mark - - -// The following methods are implemented so that `[NSPredicate predicateWithFormat:@"%K", attribute]` will work - -- (NSString *)description { - return self.name; -} - -- (NSRange)rangeOfString:(NSString *)aString { - return [self.name rangeOfString:aString]; -} - -- (NSArray *)componentsSeparatedByString:(NSString *)separator { - return [self.name componentsSeparatedByString:separator]; -} - -- (NSUInteger)length { - return [self.name length]; -} - -#pragma mark - Comparison - -- (NSPredicate *)predicateWithRightExpression:(NSExpression *)expression modifier:(NSComparisonPredicateModifier)modifier type:(NSPredicateOperatorType)type options:(NSComparisonPredicateOptions)options { - NSExpression *leftExpression = [self expression]; - return [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression:expression modifier:modifier type:type options:options]; -} - -@end - -@implementation QKAttribute (Predicate) - -- (NSPredicate *)equal:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:options]; -} - -- (NSPredicate *)equal:(id)value { - return [self equal:value options:0]; -} - -- (NSPredicate *)notEqual:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSNotEqualToPredicateOperatorType options:options]; -} - -- (NSPredicate *)notEqual:(id)value { - return [self notEqual:value options:0]; -} - -- (NSPredicate *)beginsWith:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSBeginsWithPredicateOperatorType options:options]; -} - -- (NSPredicate *)beginsWith:(id)value { - return [self beginsWith:value options:0]; -} - -- (NSPredicate *)endsWith:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEndsWithPredicateOperatorType options:options]; -} - -- (NSPredicate *)endsWith:(id)value { - return [self endsWith:value options:0]; -} - -- (NSPredicate *)like:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLikePredicateOperatorType options:options]; -} - -- (NSPredicate *)like:(id)value { - return [self like:value options:0]; -} - -- (NSPredicate *)matches:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSMatchesPredicateOperatorType options:options]; -} - -- (NSPredicate *)matches:(id)value { - return [self matches:value options:0]; -} - -- (NSPredicate *)greaterThan:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSGreaterThanPredicateOperatorType options:0]; -} - -- (NSPredicate *)greaterThanOrEqualTo:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSGreaterThanOrEqualToPredicateOperatorType options:0]; -} - -- (NSPredicate *)lessThan:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLessThanPredicateOperatorType options:0]; -} - -- (NSPredicate *)lessThanOrEqualTo:(id)value { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSLessThanOrEqualToPredicateOperatorType options:0]; -} - -- (NSPredicate *)isNil { - NSExpression *expression = [NSExpression expressionForConstantValue:nil]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; -} - -- (NSPredicate *)between:(id)minimumValue and:(id)maxiumValue { - NSExpression *expression = [NSExpression expressionForConstantValue:@[minimumValue, maxiumValue]]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSBetweenPredicateOperatorType options:0]; -} - -- (NSPredicate *)in:(id)set { - NSExpression *expression = [NSExpression expressionForConstantValue:set]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0]; -} - -- (NSPredicate *)contains:(id)value options:(NSComparisonPredicateOptions)options { - NSExpression *expression = [NSExpression expressionForConstantValue:value]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSContainsPredicateOperatorType options:options]; -} - -- (NSPredicate *)contains:(id)value { - return [self contains:value options:0]; -} - -- (NSPredicate *)isYes { - NSExpression *expression = [NSExpression expressionForConstantValue:@YES]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; -} - -- (NSPredicate *)isNo { - NSExpression *expression = [NSExpression expressionForConstantValue:@NO]; - return [self predicateWithRightExpression:expression modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; -} - -@end - -@implementation QKAttribute (Sorting) - -- (NSSortDescriptor *)ascending { - return [[NSSortDescriptor alloc] initWithKey:self.name ascending:YES]; -} - -- (NSSortDescriptor *)descending { - return [[NSSortDescriptor alloc] initWithKey:self.name ascending:NO]; -} - -@end diff --git a/QueryKit/ObjectiveC/QKAttribute.swift b/QueryKit/ObjectiveC/QKAttribute.swift deleted file mode 100644 index fd3a5ba..0000000 --- a/QueryKit/ObjectiveC/QKAttribute.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -extension Attribute { - public func asQKAttribute() -> QKAttribute { - return QKAttribute(name: key) - } -} - -extension QKAttribute { - public func asAttribute() -> Attribute { - return Attribute(name) - } -} diff --git a/QueryKit/ObjectiveC/QKQuerySet.h b/QueryKit/ObjectiveC/QKQuerySet.h deleted file mode 100644 index e1ceb06..0000000 --- a/QueryKit/ObjectiveC/QKQuerySet.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// QKQuerySet.h -// QueryKit -// -// Created by Kyle Fuller on 30/04/2013. -// -// - -#import -#import - -/** - Represents a lazy Core Data lookup for a set of objects. - - This object is immutable, any changes will normally be done to a copy. Such - as with the `-filter:`, `-exclude:`, `-orderBy:` and `-reverse` methods. - */ - -@interface QKQuerySet : NSObject - -/// The managed object context for the query set -@property (nonatomic, strong, readonly, nonnull) NSManagedObjectContext *managedObjectContext; - -/// The entity descriptor for the object -@property (nonatomic, strong, readonly, nonnull) NSEntityDescription *entityDescription; - -/** This is a read only property to hold any predicates set on this object. You can use the `filter:` and `exclude:` methods to effect this value on a child */ -@property (nonatomic, copy, readonly, nullable) NSPredicate *predicate; - -/** This is a read only property to hold any sort descriptors set on this object. You can use the `orderBy:` and `reverse` methods to effect this value on a child */ -@property (nonatomic, copy, readonly, nonnull) NSArray *sortDescriptors; - -/** This is a read only property to hold a range set. */ -@property (nonatomic, assign, readonly) NSRange range; - -#pragma mark - Creation - -- (nonnull instancetype)initWithManagedObjectContext:(NSManagedObjectContext * __nonnull)managedObjectContext entityDescription:(NSEntityDescription * __nonnull)entityDescription; -- (nonnull instancetype)initWithManagedObjectContext:(NSManagedObjectContext * __nonnull)managedObjectContext entityDescription:(NSEntityDescription * __nonnull)entityDescription predicate:(NSPredicate * __nullable)predicate sortDescriptors:(NSArray * __nullable)sortDescriptors range:(NSRange)range; -- (nonnull instancetype)initWithManagedObjectContext:(NSManagedObjectContext * __nonnull)managedObjectContext fetchRequest:(NSFetchRequest * __nonnull)fetchRequest; - -#pragma mark - Equality - -/** Returns a Boolean value that indicates whether a given queryset is equal to the receiver - @param queryset The queryset to compare against the receiver - @return YES if queryset is equivalent to the receiver - */ -- (BOOL)isEqualToQuerySet:(nonnull QKQuerySet *)queryset; - -#pragma mark - - -/** Returns a fetch request for the queryset */ -- (nonnull NSFetchRequest *)fetchRequest; - -/** Returns the amount of objects matching the set predicate - @param error If there is a problem fetching the count, upon return contains an instance of NSError that describes the problem. - @return The number of objects matching the set predicate - */ -- (NSUInteger)count:(NSError * __nullable* __nullable)error; - -/** Returns all objects matching the set predicate ordered by any set sort descriptors as an array - @param error If there is a problem fetching the objects, upon return contains an instance of NSError that describes the problem. - @return An array containing all matched objects - */ -- (nullable NSArray *)array:(NSError * __nullable* __nullable)error; - -/** Returns all objects matching the set predicate ordered by any set sort descriptors as an ordered set - @param error If there is a problem fetching the objects, upon return contains an instance of NSError that describes the problem. - @return An ordered set containing all matched objects - */ -- (nullable NSSet *)set:(NSError * __nullable* __nullable)error; - -/** Returns all objects matching the set predicate ordered by any set sort descriptors as a set - @param error If there is a problem fetching the objects, upon return contains an instance of NSError that describes the problem. - @return A set containing all matched objects - */ -- (nullable NSOrderedSet *)orderedSet:(NSError * __nullable* __nullable)error; - -#pragma mark - Enumeration - -/** Enumerate all objects matching the set predicate ordered by any set sort descriptors - @param block The block to apply to elements in the array - @param error If there is a problem fetching the objects, upon return contains an instance of NSError that describes the problem. - @return YES if the operation succeeded. - */ -- (BOOL)enumerateObjects:(nonnull void (^)(NSManagedObject * - __nonnull object, NSUInteger index, BOOL * __nonnull stop))block error:(NSError * __nullable* __nullable)error; - -/** Enumerate all objects matching the set predicate ordered by any set sort descriptors - @param block The block to apply to all objects - @param error If there is a problem fetching the objects, upon return contains an instance of NSError that describes the problem. - @return YES if the operation succeeded. - */ -- (BOOL)each:(nonnull void (^)(NSManagedObject * __nonnull managedObject))block error:(NSError * __nullable* __nullable)error; - -#pragma mark - Deletion - -/** Delete all objects matching the set predicate - @param error If there is a problem deleting the objects, upon return contains an instance of NSError that describes the problem. - @return Returns the amount of objects that were deleted - */ -- (NSUInteger)deleteObjects:(NSError * __nullable* __nullable)error; - -@end - -/// Methods to sort an query set -@interface QKQuerySet (Sorting) - -/** Returns a copy and the sort descriptors */ -- (nonnull instancetype)orderBy:(nonnull NSArray * )sortDescriptors; - -/** Returns a copy and reverses any sort descriptors */ -- (nonnull instancetype)reverse; - -@end - -/// Filtering related methods of QKQuerySet -@interface QKQuerySet (Filtering) - -/** Returns a copy filtered by a predicate */ -- (nonnull instancetype)filter:(nonnull NSPredicate *)predicate; - -/** Returns a copy excluding a predicate */ -- (nonnull instancetype)exclude:(nonnull NSPredicate *)predicate; - -@end - -/// Fetching single objects in QKQuerySet -@interface QKQuerySet (SingleObject) - -/** Returns a single object matching the filters, if there is more than one. An error will instead be returned. - @param error If there is a problem fetching the object or there is more than one object, upon return contains an instance of NSError that describes the problem. - @return Returns the object matching the set predicate, or nil. - */ -- (nullable NSManagedObject *)object:(NSError * __nullable* __nullable)error; - -/** Returns the first object matching the filters ordered by the set sort descriptors. - @param error If there is a problem fetching the object, upon return contains an instance of NSError that describes the problem. - @return Returns the first object matching the set predicate, or nil. - */ -- (nullable NSManagedObject *)firstObject:(NSError * __nullable* __nullable)error; - -/** Returns the last object matching the filters ordered by the set sort descriptors. - @param error If there is a problem fetching the object, upon return contains an instance of NSError that describes the problem. - @return Returns the last object matching the set predicate, or nil. - */ -- (nullable NSManagedObject *)lastObject:(NSError * __nullable* __nullable)error; - -@end - -/// Creating a queryset for a managed object -@interface NSManagedObject (QKQuerySet) - -/// Returns a queryset for this object in the given context. -+ (nonnull QKQuerySet *)querySetWithManagedObjectContext:(nonnull NSManagedObjectContext *)context; - -@end diff --git a/QueryKit/ObjectiveC/QKQuerySet.m b/QueryKit/ObjectiveC/QKQuerySet.m deleted file mode 100644 index 23ec919..0000000 --- a/QueryKit/ObjectiveC/QKQuerySet.m +++ /dev/null @@ -1,272 +0,0 @@ -#import "QKQuerySet.h" - -NSString * const QKQuerySetErrorDomain = @"QKQuerySetErrorDomain"; - -@interface QKQuerySet () - -@property (nonatomic, strong) NSArray *resultsCache; - -@end - -@implementation QKQuerySet - -#pragma mark - Creation - -- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription { - return [self initWithManagedObjectContext:managedObjectContext entityDescription:entityDescription predicate:nil sortDescriptors:nil range:NSMakeRange(NSNotFound, NSNotFound)]; -} - -- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest { - return [self initWithManagedObjectContext:managedObjectContext entityDescription:fetchRequest.entity predicate:fetchRequest.predicate sortDescriptors:fetchRequest.sortDescriptors range:NSMakeRange(NSNotFound, NSNotFound)]; -} - -- (instancetype)initWithManagedObjectContext:(NSManagedObjectContext *)managedObjectContext entityDescription:(NSEntityDescription *)entityDescription predicate:(NSPredicate *)predicate sortDescriptors:(NSArray *)sortDescriptors range:(NSRange)range { - if (self = [super init]) { - _managedObjectContext = managedObjectContext; - _entityDescription = entityDescription; - _predicate = [predicate copy]; - _sortDescriptors = sortDescriptors? [sortDescriptors copy] : @[]; - _range = range; - } - - return self; -} - -- (instancetype)init { - NSString *reason = [NSString stringWithFormat:@"%@ Failed to call designated initializer.", NSStringFromClass([self class])]; - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil]; -} - -#pragma mark - Equality - -- (NSUInteger)hash { - return [self.managedObjectContext hash]; -} - -- (BOOL)isEqual:(id)object { - return (self == object) || ([object isKindOfClass:[QKQuerySet class]] && [self isEqualToQuerySet:object]); -} - -- (BOOL)isEqualToQuerySet:(QKQuerySet *)queryset { - return [self.managedObjectContext isEqual:[queryset managedObjectContext]] && [self.entityDescription isEqual:[queryset entityDescription]] && [self.predicate isEqual:[queryset predicate]] && [self.sortDescriptors isEqual:[queryset sortDescriptors]] && NSEqualRanges(self.range, queryset.range); -} - -#pragma mark - NSCopying - -- (instancetype)copyWithZone:(NSZone *)zone { - return [[[self class] allocWithZone:zone] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:self.predicate sortDescriptors:self.sortDescriptors range:self.range]; -} - -#pragma mark - NSFastEnumeration - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { - return [[self array:nil] countByEnumeratingWithState:state objects:buffer count:len]; -} - -#pragma mark - Fetching - -- (NSFetchRequest *)fetchRequest { - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:_entityDescription]; - [fetchRequest setPredicate:self.predicate]; - [fetchRequest setSortDescriptors:self.sortDescriptors]; - - if (self.range.location != NSNotFound) { - fetchRequest.fetchOffset = self.range.location; - fetchRequest.fetchLimit = self.range.length; - } - - return fetchRequest; -} - -- (NSUInteger)count:(NSError **)error { - NSUInteger count = 0; - - if (_resultsCache) { - count = [_resultsCache count]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - count = [self.managedObjectContext countForFetchRequest:fetchRequest error:error]; - } - - return count; -} - -- (NSArray *)array:(NSError **)error { - if (_resultsCache == nil) { - _resultsCache = [self.managedObjectContext executeFetchRequest:[self fetchRequest] error:error]; - } - - return _resultsCache; -} - -- (NSSet *)set:(NSError **)error { - NSArray *array = [self array:error]; - NSSet *set; - - if (array != nil) { - set = [NSSet setWithArray:array]; - } - - return set; -} - -- (NSOrderedSet *)orderedSet:(NSError **)error { - NSArray *array = [self array:error]; - NSOrderedSet *orderedSet; - - if (array != nil) { - orderedSet = [NSOrderedSet orderedSetWithArray:array]; - } - - return orderedSet; -} - -- (BOOL)enumerateObjects:(void (^)(NSManagedObject *object, NSUInteger index, BOOL *stop))block error:(NSError **)error { - NSArray *array = [self array:error]; - - if (array != nil) { - [array enumerateObjectsUsingBlock:block]; - } - - return array != nil; -} - -- (BOOL)each:(void (^)(NSManagedObject *managedObject))block error:(NSError **)error { - return [self enumerateObjects:^(NSManagedObject * _Nonnull object, NSUInteger index, BOOL * _Nonnull stop) { - block(object); - } error:error]; -} - -#pragma mark - Deletion - -- (NSUInteger)deleteObjects:(NSError **)error { - NSArray *array = [self array:error]; - - NSUInteger count = 0; - - if (array != nil) { - NSManagedObjectContext *managedObjectContext = self.managedObjectContext; - - for (NSManagedObject *managedObject in array) { - [managedObjectContext deleteObject:managedObject]; - ++count; - } - } - - return count; -} - -@end - -@implementation QKQuerySet (Sorting) - -- (instancetype)orderBy:(NSArray *)sortDescriptors { - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; -} - -- (instancetype)reverse { - NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithCapacity:[_sortDescriptors count]]; - - for (NSSortDescriptor *sortDescriptor in _sortDescriptors) { - [sortDescriptors addObject:[sortDescriptor reversedSortDescriptor]]; - } - - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:_predicate sortDescriptors:sortDescriptors range:self.range]; -} - -@end - -@implementation QKQuerySet (Filtering) - -- (instancetype)exclude:(NSPredicate *)predicate { - predicate = [[NSCompoundPredicate alloc] initWithType:NSNotPredicateType subpredicates:@[predicate]]; - - if (_predicate) { - predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; - } - - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; -} - -- (instancetype)filter:(NSPredicate *)predicate { - if (_predicate) { - predicate = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:@[_predicate, predicate]]; - } - - return [[QKQuerySet alloc] initWithManagedObjectContext:_managedObjectContext entityDescription:_entityDescription predicate:predicate sortDescriptors:_sortDescriptors range:self.range]; -} - -@end - -@implementation QKQuerySet (SingleObject) - -- (NSManagedObject *)object:(NSError **)error { - NSManagedObject *managedObject; - NSArray *array; - - if (_resultsCache) { - array = _resultsCache; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - fetchRequest.fetchBatchSize = 1; // Only request one - - array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - } - - NSUInteger count = [array count]; - - if (count == 1) { - managedObject = [array firstObject]; - } else if ((count > 1) && error != nil) { - NSString *errorDescription = @"Find object in fetch request failed, should only result in a single result."; - *error = [NSError errorWithDomain:QKQuerySetErrorDomain code:0 userInfo:@{ NSLocalizedDescriptionKey: errorDescription }]; - } - - return managedObject; -} - -- (NSManagedObject *)firstObject:(NSError **)error { - NSManagedObject *managedObject; - - if (_resultsCache) { - managedObject = [_resultsCache firstObject]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - [fetchRequest setFetchLimit:1]; - - NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - managedObject = [array firstObject]; - } - - return managedObject; -} - -- (NSManagedObject *)lastObject:(NSError **)error { - NSManagedObject *managedObject; - - if (_resultsCache) { - managedObject = [_resultsCache lastObject]; - } else { - NSFetchRequest *fetchRequest = [self fetchRequest]; - NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:error]; - managedObject = [array lastObject]; - } - - return managedObject; -} - -@end - -@implementation NSManagedObject (QKQuerySet) - -+ (NSString *)entityName { - return NSStringFromClass([self class]); -} - -+ (QKQuerySet *)querySetWithManagedObjectContext:(NSManagedObjectContext *)context { - NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:context]; - return [[QKQuerySet alloc] initWithManagedObjectContext:context entityDescription:entityDescription]; -} - -@end diff --git a/QueryKit/ObjectiveC/QKQuerySet.swift b/QueryKit/ObjectiveC/QKQuerySet.swift deleted file mode 100644 index 5213329..0000000 --- a/QueryKit/ObjectiveC/QKQuerySet.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Foundation - -extension QuerySet { - public func asQKQuerySet() -> QKQuerySet { - let entityDescription = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)! - - var nsrange:NSRange = NSMakeRange(NSNotFound, NSNotFound) - if let range = self.range { - nsrange = NSMakeRange(range.startIndex, range.endIndex - range.startIndex) - } - - return QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:nsrange) - } -} - -extension QKQuerySet { - public func asQuerySet() -> QuerySet { - var queryset = QuerySet(managedObjectContext, entityDescription.name!) - - if let sortDescriptors = sortDescriptors as? [NSSortDescriptor] { - queryset = queryset.orderBy(sortDescriptors) - } - - if let predicate = predicate { - queryset = queryset.filter(predicate) - } - - if range.location != NSNotFound { - queryset = queryset[range.location..<(range.location + range.length)] - } - - return queryset - } -} diff --git a/QueryKit/QueryKit.h b/QueryKit/QueryKit.h index f4d7312..80cf39f 100644 --- a/QueryKit/QueryKit.h +++ b/QueryKit/QueryKit.h @@ -4,8 +4,4 @@ FOUNDATION_EXPORT double QueryKitVersionNumber; //! Project version string for QueryKit. -FOUNDATION_EXPORT const unsigned char QueryKitVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import -#import -#import +FOUNDATION_EXPORT const unsigned char QueryKitVersionString[]; \ No newline at end of file diff --git a/QueryKitTests/Info.plist b/QueryKitTests/Info.plist index 6d32c15..ba72822 100644 --- a/QueryKitTests/Info.plist +++ b/QueryKitTests/Info.plist @@ -5,13 +5,13 @@ CFBundleDevelopmentRegion en CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString diff --git a/QueryKitTests/ObjectiveC/QKAttributeTests.swift b/QueryKitTests/ObjectiveC/QKAttributeTests.swift deleted file mode 100644 index f042aac..0000000 --- a/QueryKitTests/ObjectiveC/QKAttributeTests.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// QKAttributeTests.swift -// QueryKit -// -// Created by Kyle Fuller on 23/08/2014. -// -// - -import XCTest -import QueryKit - -class QKAttributeTests: XCTestCase { - var attribute:QKAttribute! - - override func setUp() { - super.setUp() - - attribute = QKAttribute(name: "age") - } - - func testAttributeHasName() { - XCTAssertEqual(attribute.name, "age") - } - - func testAttributeExpression() { - XCTAssertEqual(attribute.expression().keyPath, "age") - } - - func testEqualAttributesAreEquatable() { - XCTAssertEqual(attribute, QKAttribute(name: "age")) - } - - // MARK: Conversion - - func testConvertingAttributeToQKAttribute() { - let qkAttribute = Attribute("age").asQKAttribute() - XCTAssertEqual(qkAttribute, attribute) - } - - func testConvertingQKAttributeToAttribute() { - XCTAssertEqual(attribute.asAttribute(), Attribute("age")) - } - - // MARK: Ordering - - func testAscendingSortDescriptor() { - XCTAssertEqual(attribute.ascending(), NSSortDescriptor(key: "age", ascending: true)) - } - - func testDescendingSortDescriptor() { - XCTAssertEqual(attribute.descending(), NSSortDescriptor(key: "age", ascending: false)) - } - - // MARK: Operators - - func testEqualityOperator() { - let predicate = attribute.equal(10) - XCTAssertEqual(predicate, NSPredicate(format:"age == 10")) - } - - func testInequalityOperator() { - let predicate = attribute.notEqual(10) - XCTAssertEqual(predicate, NSPredicate(format:"age != 10")) - } - - func testGreaterThanOperator() { - let predicate = attribute.greaterThan(10) - XCTAssertEqual(predicate, NSPredicate(format:"age > 10")) - } - - func testGreaterOrEqualThanOperator() { - let predicate = attribute.greaterThanOrEqualTo(10) - XCTAssertEqual(predicate, NSPredicate(format:"age >= 10")) - } - - func testLessThanOperator() { - let predicate = attribute.lessThan(10) - XCTAssertEqual(predicate, NSPredicate(format:"age < 10")) - } - - func testLessOrEqualThanOperator() { - let predicate = attribute.lessThanOrEqualTo(10) - XCTAssertEqual(predicate, NSPredicate(format:"age <= 10")) - } -} diff --git a/QueryKitTests/ObjectiveC/QKQuerySetTests.m b/QueryKitTests/ObjectiveC/QKQuerySetTests.m deleted file mode 100644 index 44b0a20..0000000 --- a/QueryKitTests/ObjectiveC/QKQuerySetTests.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// KFObjectManagerTests -// KFDataTests -// -// Created by Kyle Fuller on 14/06/2013. -// -// - -#import -#import - - -@interface QKQuerySetTests : XCTestCase - -@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; -@property (nonatomic, strong) NSEntityDescription *entityDescription; -@property (nonatomic, strong) QKQuerySet *queryset; - -@end - -@implementation QKQuerySetTests - -- (void)setUp { - self.managedObjectContext = [[NSManagedObjectContext alloc] init]; - self.entityDescription = [[NSEntityDescription alloc] init]; - - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - self.queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; -} - -- (void)testInitializationWithContextAndEntityDescription { - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription]; - - XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); - XCTAssertNil(queryset.predicate); - XCTAssertEqualObjects(queryset.sortDescriptors, @[]); -} - -- (void)testInitializationWithPredicateAndSortDescriptors { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - XCTAssertEqualObjects(self.queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(self.queryset.entityDescription, self.entityDescription); - XCTAssertEqualObjects(self.queryset.predicate, predicate); - XCTAssertEqualObjects(self.queryset.sortDescriptors, sortDescriptors); -} - -- (void)testCreationFromFetchRequest { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; - - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:self.entityDescription]; - [fetchRequest setPredicate:predicate]; - [fetchRequest setSortDescriptors:sortDescriptors]; - - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext fetchRequest:fetchRequest]; - - XCTAssertEqualObjects(queryset.managedObjectContext, self.managedObjectContext); - XCTAssertEqualObjects(queryset.entityDescription, self.entityDescription); - XCTAssertEqualObjects(queryset.predicate, predicate); - XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); -} - -- (void)testIsEqual { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - QKQuerySet *queryset = [[QKQuerySet alloc] initWithManagedObjectContext:self.managedObjectContext entityDescription:self.entityDescription predicate:predicate sortDescriptors:sortDescriptors range:NSMakeRange(1, 3)]; - - XCTAssertEqualObjects(self.queryset, queryset); - XCTAssertEqual([self.queryset hash], [queryset hash]); -} - -- (void)testCopying { - QKQuerySet *queryset = [self.queryset copy]; - XCTAssertEqualObjects(self.queryset, queryset); -} - -- (void)testFilterAddsPredicate { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; - QKQuerySet *filteredQuerySet = [self.queryset filter:predicate]; - - XCTAssertEqualObjects(filteredQuerySet.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND age == 28"]); -} - -- (void)testExcludeAddsPredicate { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age == 28"]; - QKQuerySet *queryset = [self.queryset exclude:predicate]; - - XCTAssertEqualObjects(queryset.predicate, [NSPredicate predicateWithFormat:@"name == 'Kyle' AND (NOT age == 28)"]); -} - -- (void)testOrderBy { - NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]; - QKQuerySet *queryset = [self.queryset orderBy:sortDescriptors]; - - XCTAssertEqualObjects(queryset.sortDescriptors, sortDescriptors); -} - -- (void)testReverse { - QKQuerySet *reversedQueryset = [self.queryset reverse]; - - NSArray *reversedSortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES] - ]; - - XCTAssertEqualObjects(reversedQueryset.sortDescriptors, reversedSortDescriptors); -} - -- (void)testFetchRequest { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == 'Kyle'"]; - NSArray *sortDescriptors = @[ - [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES], - [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO] - ]; - - NSFetchRequest *fetchRequest = [self.queryset fetchRequest]; - - XCTAssertEqualObjects(fetchRequest.entityName, self.entityDescription.name); - XCTAssertEqualObjects(fetchRequest.predicate, predicate); - XCTAssertEqualObjects(fetchRequest.sortDescriptors, sortDescriptors); - XCTAssertEqual(fetchRequest.fetchOffset, 1); - XCTAssertEqual(fetchRequest.fetchLimit, 3); -} - -@end diff --git a/QueryKitTests/ObjectiveC/QKQuerySetTests.swift b/QueryKitTests/ObjectiveC/QKQuerySetTests.swift deleted file mode 100644 index c9149ce..0000000 --- a/QueryKitTests/ObjectiveC/QKQuerySetTests.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// QuerySetTests.swift -// QueryKit -// -// Created by Kyle Fuller on 06/07/2014. -// -// - -import XCTest -import QueryKit - -class QKQuerySetConversionTests: XCTestCase { - var qkQueryset:QKQuerySet! - var queryset:QuerySet! - - override func setUp() { - super.setUp() - - let context = NSManagedObjectContext() - context.persistentStoreCoordinator = persistentStoreCoordinator() - let entityDescription = NSEntityDescription.entityForName("Person", inManagedObjectContext:context)! - let predicate = NSPredicate(format: "name == 'Kyle'") - let sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] - - qkQueryset = QKQuerySet(managedObjectContext: context, entityDescription: entityDescription, predicate: predicate, sortDescriptors: sortDescriptors, range:NSMakeRange(1, 4)) - queryset = QuerySet(context, "Person") - queryset = queryset.filter(predicate).orderBy(sortDescriptors)[1..<5] - } - - func testConvertingQuerySetToQKQuerySet() { - XCTAssertEqual(queryset.asQKQuerySet(), qkQueryset) - } - - func testConvertingQKQuerySetToQuerySet() { - XCTAssertEqual(qkQueryset.asQuerySet(), queryset) - } -} diff --git a/QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h b/QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h deleted file mode 100644 index 1b2cb5d..0000000 --- a/QueryKitTests/ObjectiveC/QueryKitTests-Bridging-Header.h +++ /dev/null @@ -1,4 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - diff --git a/QueryKitTests/Person.h b/QueryKitTests/Person.h deleted file mode 100644 index 884af31..0000000 --- a/QueryKitTests/Person.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Person.h -// QueryKit -// -// Created by Kyle Fuller on 06/07/2014. -// -// - -#import - -@interface Person : NSManagedObject - -@property (nonatomic, retain) NSString *name; - -@end From 8347af94ca8eea9037833ef83df9fb1eaf6195fa Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 08:22:42 -0800 Subject: [PATCH 52/71] Release 0.12.0 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 7de46ae..855b7ba 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.11.1' + spec.version = '0.12.0' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From ad0d34570e0dbb6976ea9a0d2b5c5f837bc38698 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 11:07:56 -0800 Subject: [PATCH 53/71] Restore Carthage support and support tvOS --- QueryKit.podspec | 1 + QueryKit.xcodeproj/project.pbxproj | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/QueryKit.podspec b/QueryKit.podspec index 855b7ba..45695cd 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -11,6 +11,7 @@ Pod::Spec.new do |spec| spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' spec.watchos.deployment_target = '2.0' + spec.tvos.deployment_target = '9.0' spec.frameworks = 'CoreData' spec.source_files = 'QueryKit/*.swift' end diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 17851a8..4fe318b 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -287,13 +287,16 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Debug; }; @@ -328,11 +331,14 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; }; name = Release; }; From 0c7b4c3c5a5ef32591c80789bf16c3266d46b5f1 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 6 Nov 2015 11:08:14 -0800 Subject: [PATCH 54/71] Release 0.12.1 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 45695cd..f6164bc 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.12.0' + spec.version = '0.12.1' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From 2743261253d5a7134e4959010dd8432b09207345 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Thu, 15 Sep 2016 09:34:42 +0100 Subject: [PATCH 55/71] Update to Swift 3.0 --- QueryKit.xcodeproj/project.pbxproj | 15 +++- .../xcshareddata/xcschemes/QueryKit.xcscheme | 2 +- QueryKit/Attribute.swift | 24 +++--- QueryKit/Expression.swift | 16 ++-- QueryKit/Predicate.swift | 6 +- QueryKit/QuerySet.swift | 82 +++++++++---------- QueryKitTests/QueryKitTests.swift | 24 +++--- 7 files changed, 87 insertions(+), 82 deletions(-) diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index 4fe318b..bd202ab 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -172,14 +172,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = QueryKit; TargetAttributes = { 279ED57F1BED09EB0011CA09 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; }; 279ED5891BED09EB0011CA09 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; }; }; }; @@ -263,8 +265,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -313,8 +317,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; @@ -335,6 +341,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -347,6 +354,7 @@ baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -360,6 +368,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -368,6 +377,7 @@ baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -380,6 +390,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -392,6 +403,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -404,6 +416,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme index d332541..434d561 100644 --- a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme +++ b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme @@ -1,6 +1,6 @@ : Equatable { /// Builds a compound attribute with other key paths public init(attributes:[String]) { - self.init(attributes.joinWithSeparator(".")) + self.init(attributes.joined(separator: ".")) } /// Returns an expression for the attribute @@ -30,20 +30,20 @@ public struct Attribute : Equatable { return NSSortDescriptor(key: key, ascending: false) } - func expressionForValue(value:AttributeType?) -> NSExpression { + func expressionForValue(_ value:AttributeType?) -> NSExpression { if let value = value { if let value = value as? NSObject { return NSExpression(forConstantValue: value as NSObject) } - if sizeof(value.dynamicType) == sizeof(uintptr_t) { - let value = unsafeBitCast(value, Optional.self) + if MemoryLayout.size == MemoryLayout.size { + let value = unsafeBitCast(value, to: Optional.self) if let value = value { return NSExpression(forConstantValue: value) } } - let value = unsafeBitCast(value, Optional.self) + let value = unsafeBitCast(value, to: Optional.self) if let value = value { return NSExpression(forConstantValue: value) } @@ -53,7 +53,7 @@ public struct Attribute : Equatable { } /// Builds a compound attribute by the current attribute with the given attribute - public func attribute(attribute:Attribute) -> Attribute { + public func attribute(_ attribute:Attribute) -> Attribute { return Attribute(attributes: [key, attribute.key]) } } @@ -98,10 +98,10 @@ public func << (left: Attribute, right: [Attribute } public func << (left: Attribute, right: Range) -> NSPredicate { - let value = [right.startIndex as! NSObject, right.endIndex as! NSObject] as NSArray + let value = [right.lowerBound as! NSObject, right.upperBound as! NSObject] as NSArray let rightExpression = NSExpression(forConstantValue: value) - return NSComparisonPredicate(leftExpression: left.expression, rightExpression: rightExpression, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.BetweenPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left.expression, rightExpression: rightExpression, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.between, options: NSComparisonPredicate.Options(rawValue: 0)) } /// MARK: Bool Attributes @@ -111,21 +111,21 @@ prefix public func ! (left: Attribute) -> NSPredicate { } public extension QuerySet { - public func filter(attribute:Attribute) -> QuerySet { + public func filter(_ attribute:Attribute) -> QuerySet { return filter(attribute == true) } - public func exclude(attribute:Attribute) -> QuerySet { + public func exclude(_ attribute:Attribute) -> QuerySet { return filter(attribute == false) } } // MARK: Collections -public func count(attribute:Attribute) -> Attribute { +public func count(_ attribute:Attribute) -> Attribute { return Attribute(attributes: [attribute.key, "@count"]) } -public func count(attribute:Attribute) -> Attribute { +public func count(_ attribute:Attribute) -> Attribute { return Attribute(attributes: [attribute.key, "@count"]) } diff --git a/QueryKit/Expression.swift b/QueryKit/Expression.swift index b91507c..546756a 100644 --- a/QueryKit/Expression.swift +++ b/QueryKit/Expression.swift @@ -2,34 +2,34 @@ import Foundation /// Returns an equality predicate for the two given expressions public func == (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.equalTo, options: NSComparisonPredicate.Options(rawValue: 0)) } /// Returns an inequality predicate for the two given expressions public func != (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.NotEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.notEqualTo, options: NSComparisonPredicate.Options(rawValue: 0)) } public func > (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.greaterThan, options: NSComparisonPredicate.Options(rawValue: 0)) } public func >= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.greaterThanOrEqualTo, options: NSComparisonPredicate.Options(rawValue: 0)) } public func < (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.lessThan, options: NSComparisonPredicate.Options(rawValue: 0)) } public func <= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.lessThanOrEqualTo, options: NSComparisonPredicate.Options(rawValue: 0)) } public func ~= (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.LikePredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.like, options: NSComparisonPredicate.Options(rawValue: 0)) } public func << (left: NSExpression, right: NSExpression) -> NSPredicate { - return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.InPredicateOperatorType, options: NSComparisonPredicateOptions(rawValue: 0)) + return NSComparisonPredicate(leftExpression: left, rightExpression: right, modifier: NSComparisonPredicate.Modifier.direct, type: NSComparisonPredicate.Operator.in, options: NSComparisonPredicate.Options(rawValue: 0)) } diff --git a/QueryKit/Predicate.swift b/QueryKit/Predicate.swift index 2a97b0a..a13b9cf 100644 --- a/QueryKit/Predicate.swift +++ b/QueryKit/Predicate.swift @@ -3,17 +3,17 @@ import CoreData /// Returns an and predicate from the given predicates public func && (left: NSPredicate, right: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [left, right]) + return NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: [left, right]) } /// Returns an or predicate from the given predicates public func || (left: NSPredicate, right: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [left, right]) + return NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: [left, right]) } /// Returns a predicate reversing the given predicate prefix public func ! (left: NSPredicate) -> NSPredicate { - return NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [left]) + return NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.not, subpredicates: [left]) } // MARK: Predicate Type diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index e55d7e5..7ee7745 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -2,21 +2,21 @@ import Foundation import CoreData /// Represents a lazy database lookup for a set of objects. -public class QuerySet : Equatable { +open class QuerySet : Equatable { /// Returns the managed object context that will be used to execute any requests. - public let context:NSManagedObjectContext + open let context:NSManagedObjectContext /// Returns the name of the entity the request is configured to fetch. - public let entityName:String + open let entityName:String /// Returns the sort descriptors of the receiver. - public let sortDescriptors:[NSSortDescriptor] + open let sortDescriptors:[NSSortDescriptor] /// Returns the predicate of the receiver. - public let predicate:NSPredicate? + open let predicate:NSPredicate? /// The range of the query, allows you to offset and limit a query - public let range:Range? + open let range: Range? // MARK: Initialization @@ -29,7 +29,7 @@ public class QuerySet : Equatable { } /// Create a queryset from another queryset with a different sortdescriptor predicate and range - public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range:Range?) { + public init(queryset:QuerySet, sortDescriptors:[NSSortDescriptor]?, predicate:NSPredicate?, range: Range?) { self.context = queryset.context self.entityName = queryset.entityName self.sortDescriptors = sortDescriptors ?? [] @@ -43,18 +43,18 @@ extension QuerySet { // MARK: Sorting /// Returns a new QuerySet containing objects ordered by the given sort descriptor. - public func orderBy(sortDescriptor:NSSortDescriptor) -> QuerySet { + public func orderBy(_ sortDescriptor:NSSortDescriptor) -> QuerySet { return orderBy([sortDescriptor]) } /// Returns a new QuerySet containing objects ordered by the given sort descriptors. - public func orderBy(sortDescriptors:[NSSortDescriptor]) -> QuerySet { + public func orderBy(_ sortDescriptors:[NSSortDescriptor]) -> QuerySet { return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:range) } /// Reverses the ordering of the QuerySet public func reverse() -> QuerySet { - func reverseSortDescriptor(sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { + func reverseSortDescriptor(_ sortDescriptor:NSSortDescriptor) -> NSSortDescriptor { return NSSortDescriptor(key: sortDescriptor.key!, ascending: !sortDescriptor.ascending) } @@ -64,65 +64,65 @@ extension QuerySet { // MARK: Type-safe Sorting /// Returns a new QuerySet containing objects ordered by the given sort descriptor. - public func orderBy(closure:((ModelType.Type) -> (SortDescriptor))) -> QuerySet { + public func orderBy(_ closure:((ModelType.Type) -> (SortDescriptor))) -> QuerySet { return orderBy(closure(ModelType.self).sortDescriptor) } /// Returns a new QuerySet containing objects ordered by the given sort descriptors. - public func orderBy(closure:((ModelType.Type) -> ([SortDescriptor]))) -> QuerySet { + public func orderBy(_ closure:((ModelType.Type) -> ([SortDescriptor]))) -> QuerySet { return orderBy(closure(ModelType.self).map { $0.sortDescriptor }) } // MARK: Filtering /// Returns a new QuerySet containing objects that match the given predicate. - public func filter(predicate:NSPredicate) -> QuerySet { + public func filter(_ predicate:NSPredicate) -> QuerySet { var futurePredicate = predicate if let existingPredicate = self.predicate { - futurePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [existingPredicate, predicate]) + futurePredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: [existingPredicate, predicate]) } return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:futurePredicate, range:range) } /// Returns a new QuerySet containing objects that match the given predicates. - public func filter(predicates:[NSPredicate]) -> QuerySet { - let newPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) + public func filter(_ predicates:[NSPredicate]) -> QuerySet { + let newPredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: predicates) return filter(newPredicate) } /// Returns a new QuerySet containing objects that exclude the given predicate. - public func exclude(predicate:NSPredicate) -> QuerySet { - let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.NotPredicateType, subpredicates: [predicate]) + public func exclude(_ predicate:NSPredicate) -> QuerySet { + let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.not, subpredicates: [predicate]) return filter(excludePredicate) } /// Returns a new QuerySet containing objects that exclude the given predicates. - public func exclude(predicates:[NSPredicate]) -> QuerySet { - let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates) + public func exclude(_ predicates:[NSPredicate]) -> QuerySet { + let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.and, subpredicates: predicates) return exclude(excludePredicate) } // MARK: Type-safe filtering /// Returns a new QuerySet containing objects that match the given predicate. - public func filter(closure:((ModelType.Type) -> (Predicate))) -> QuerySet { + public func filter(_ closure:((ModelType.Type) -> (Predicate))) -> QuerySet { return filter(closure(ModelType.self).predicate) } /// Returns a new QuerySet containing objects that exclude the given predicate. - public func exclude(closure:((ModelType.Type) -> (Predicate))) -> QuerySet { + public func exclude(_ closure:((ModelType.Type) -> (Predicate))) -> QuerySet { return exclude(closure(ModelType.self).predicate) } /// Returns a new QuerySet containing objects that match the given predicatess. - public func filter(closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { + public func filter(_ closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { return filter(closures.map { $0(ModelType.self).predicate }) } /// Returns a new QuerySet containing objects that exclude the given predicates. - public func exclude(closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { + public func exclude(_ closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { return exclude(closures.map { $0(ModelType.self).predicate }) } } @@ -132,12 +132,12 @@ extension QuerySet { // MARK: Subscripting /// Returns the object at the specified index. - public func object(index: Int) throws -> ModelType? { + public func object(_ index: Int) throws -> ModelType? { let request = fetchRequest request.fetchOffset = index request.fetchLimit = 1 - let items = try context.executeFetchRequest(request) - return items.first as? ModelType + let items = try context.fetch(request) + return items.first } public subscript(range:Range) -> QuerySet { @@ -145,7 +145,7 @@ extension QuerySet { var fullRange = range if let currentRange = self.range { - fullRange = Range(start: currentRange.startIndex + range.startIndex, end: range.endIndex) + fullRange = ((currentRange.lowerBound + range.lowerBound) ..< range.upperBound) } return QuerySet(queryset:self, sortDescriptors:sortDescriptors, predicate:predicate, range:fullRange) @@ -167,14 +167,14 @@ extension QuerySet { // MARK: Conversion /// Returns a fetch request equivilent to the QuerySet - public var fetchRequest:NSFetchRequest { - let request = NSFetchRequest(entityName:entityName) + public var fetchRequest: NSFetchRequest { + let request = NSFetchRequest(entityName: entityName) request.predicate = predicate request.sortDescriptors = sortDescriptors if let range = range { - request.fetchOffset = range.startIndex - request.fetchLimit = range.endIndex - range.startIndex + request.fetchOffset = range.lowerBound + request.fetchLimit = range.upperBound - range.lowerBound } return request @@ -182,22 +182,14 @@ extension QuerySet { /// Returns an array of all objects matching the QuerySet public func array() throws -> [ModelType] { - let objects = try context.executeFetchRequest(fetchRequest) as! [ModelType] - return objects + return try context.fetch(fetchRequest) } // MARK: Count /// Returns the count of objects matching the QuerySet. public func count() throws -> Int { - var error:NSError? - let count:Int? = context.countForFetchRequest(fetchRequest, error: &error) - - if let error = error { - throw error - } - - return count as Int! + return try context.count(for: fetchRequest) } // MARK: Exists @@ -218,7 +210,7 @@ extension QuerySet { let deletedCount = objects.count for object in objects { - context.deleteObject(object) + context.delete(object) } return deletedCount @@ -231,7 +223,7 @@ public func == (lhs: QuerySet, rhs: Quer let entityName = lhs.entityName == rhs.entityName let sortDescriptors = lhs.sortDescriptors == rhs.sortDescriptors let predicate = lhs.predicate == rhs.predicate - let startIndex = lhs.range?.startIndex == rhs.range?.startIndex - let endIndex = lhs.range?.endIndex == rhs.range?.endIndex + let startIndex = lhs.range?.lowerBound == rhs.range?.lowerBound + let endIndex = lhs.range?.upperBound == rhs.range?.upperBound return context && entityName && sortDescriptors && predicate && startIndex && endIndex } diff --git a/QueryKitTests/QueryKitTests.swift b/QueryKitTests/QueryKitTests.swift index 3b9f62f..fc429ab 100644 --- a/QueryKitTests/QueryKitTests.swift +++ b/QueryKitTests/QueryKitTests.swift @@ -38,8 +38,8 @@ import CoreData return Attribute("name") } - class func create(context:NSManagedObjectContext) -> Company { - return NSEntityDescription.insertNewObjectForEntityForName(Company.entityName, inManagedObjectContext: context) as! Company + class func create(_ context:NSManagedObjectContext) -> Company { + return NSEntityDescription.insertNewObject(forEntityName: Company.entityName, into: context) as! Company } } @@ -50,8 +50,8 @@ extension Attribute where AttributeType: Company { } extension Person { - class func create(context:NSManagedObjectContext) -> Person { - return NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as! Person + class func create(_ context:NSManagedObjectContext) -> Person { + return NSEntityDescription.insertNewObject(forEntityName: Person.entityName, into: context) as! Person } } @@ -66,8 +66,8 @@ func managedObjectModel() -> NSManagedObjectModel { let companyNameAttribute = NSAttributeDescription() companyNameAttribute.name = "name" - companyNameAttribute.attributeType = NSAttributeType.StringAttributeType - companyNameAttribute.optional = false + companyNameAttribute.attributeType = NSAttributeType.stringAttributeType + companyNameAttribute.isOptional = false let companyPeopleAttribute = NSRelationshipDescription() companyPeopleAttribute.name = "members" @@ -76,14 +76,14 @@ func managedObjectModel() -> NSManagedObjectModel { let personNameAttribute = NSAttributeDescription() personNameAttribute.name = "name" - personNameAttribute.attributeType = NSAttributeType.StringAttributeType - personNameAttribute.optional = false + personNameAttribute.attributeType = NSAttributeType.stringAttributeType + personNameAttribute.isOptional = false let personCompanyRelation = NSRelationshipDescription() personCompanyRelation.name = "company" personCompanyRelation.destinationEntity = companyEntity personCompanyRelation.maxCount = 1 - personCompanyRelation.optional = true + personCompanyRelation.isOptional = true companyPeopleAttribute.inverseRelationship = personCompanyRelation personCompanyRelation.inverseRelationship = companyPeopleAttribute @@ -101,7 +101,7 @@ func persistentStoreCoordinator() -> NSPersistentStoreCoordinator { let model = managedObjectModel() let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model) do { - try persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil) + try persistentStoreCoordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil) } catch { print(error) fatalError() @@ -109,7 +109,7 @@ func persistentStoreCoordinator() -> NSPersistentStoreCoordinator { return persistentStoreCoordinator } -public func AssertNotThrow(@autoclosure closure: () throws -> R) -> R? { +public func AssertNotThrow(_ closure: @autoclosure () throws -> R) -> R? { var result: R? AssertNotThrow() { result = try closure() @@ -117,7 +117,7 @@ public func AssertNotThrow(@autoclosure closure: () throws -> R) -> R? { return result } -public func AssertNotThrow(@noescape closure: () throws -> ()) { +public func AssertNotThrow(_ closure: () throws -> ()) { do { try closure() } catch let error { From fb870bf6a572cf1233ebe5caee77cf4cc70353c8 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Thu, 15 Sep 2016 09:35:03 +0100 Subject: [PATCH 56/71] Release 0.13.0 --- QueryKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index f6164bc..f80331f 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.12.1' + spec.version = '0.13.0' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'http://querykit.org/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From edd71f86a16087d783ddd518cc77766424c05214 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 29 Feb 2020 18:00:33 +0000 Subject: [PATCH 57/71] feat: support Swift 5 BREAKING CHANGE: Swift 3/4 is no longer supported Closes #52 Closes #53 Closes #54 --- CHANGELOG.md | 7 +++++++ QueryKit.podspec | 1 + QueryKit.xcodeproj/project.pbxproj | 7 +++---- QueryKit/Attribute.swift | 4 ++-- QueryKit/QuerySet.swift | 10 +++++----- 5 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d4638af --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# QueryKit Changelog + +## Master + +### Breaking + +* Drops support for Swift 3 and Swift 4. Swift 5 or newer must be used. diff --git a/QueryKit.podspec b/QueryKit.podspec index f80331f..07d46a1 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -8,6 +8,7 @@ Pod::Spec.new do |spec| spec.social_media_url = 'https://twitter.com/QueryKit' spec.source = { :git => 'https://github.com/QueryKit/QueryKit.git', :tag => "#{spec.version}" } spec.requires_arc = true + spec.swift_versions = ['5.0', '5.1'] spec.ios.deployment_target = '8.0' spec.osx.deployment_target = '10.9' spec.watchos.deployment_target = '2.0' diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index bd202ab..e30fa30 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -190,6 +190,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = 279ED5761BED09EB0011CA09; @@ -297,6 +298,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -342,6 +344,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -368,7 +371,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -390,7 +392,6 @@ PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; }; name = Release; }; @@ -403,7 +404,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -416,7 +416,6 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/QueryKit/Attribute.swift b/QueryKit/Attribute.swift index e39f0f0..078707b 100644 --- a/QueryKit/Attribute.swift +++ b/QueryKit/Attribute.swift @@ -111,11 +111,11 @@ prefix public func ! (left: Attribute) -> NSPredicate { } public extension QuerySet { - public func filter(_ attribute:Attribute) -> QuerySet { + func filter(_ attribute:Attribute) -> QuerySet { return filter(attribute == true) } - public func exclude(_ attribute:Attribute) -> QuerySet { + func exclude(_ attribute:Attribute) -> QuerySet { return filter(attribute == false) } } diff --git a/QueryKit/QuerySet.swift b/QueryKit/QuerySet.swift index 7ee7745..c1f0ccd 100644 --- a/QueryKit/QuerySet.swift +++ b/QueryKit/QuerySet.swift @@ -4,19 +4,19 @@ import CoreData /// Represents a lazy database lookup for a set of objects. open class QuerySet : Equatable { /// Returns the managed object context that will be used to execute any requests. - open let context:NSManagedObjectContext + public let context: NSManagedObjectContext /// Returns the name of the entity the request is configured to fetch. - open let entityName:String + public let entityName: String /// Returns the sort descriptors of the receiver. - open let sortDescriptors:[NSSortDescriptor] + public let sortDescriptors: [NSSortDescriptor] /// Returns the predicate of the receiver. - open let predicate:NSPredicate? + public let predicate: NSPredicate? /// The range of the query, allows you to offset and limit a query - open let range: Range? + public let range: Range? // MARK: Initialization From 86508067667613a1f8f098e7f899c016315299e8 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sat, 29 Feb 2020 18:01:12 +0000 Subject: [PATCH 58/71] refactor: switch to Xcode 11 defaults --- QueryKit.xcodeproj/project.pbxproj | 22 ++++++++++++++--- .../xcshareddata/xcschemes/QueryKit.xcscheme | 24 ++++++++----------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj index e30fa30..4a045db 100644 --- a/QueryKit.xcodeproj/project.pbxproj +++ b/QueryKit.xcodeproj/project.pbxproj @@ -172,7 +172,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1130; ORGANIZATIONNAME = QueryKit; TargetAttributes = { 279ED57F1BED09EB0011CA09 = { @@ -187,11 +187,11 @@ }; buildConfigurationList = 279ED57A1BED09EB0011CA09 /* Build configuration list for PBXProject "QueryKit" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, + Base, ); mainGroup = 279ED5761BED09EB0011CA09; productRefGroup = 279ED5811BED09EB0011CA09 /* Products */; @@ -261,14 +261,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -314,14 +322,22 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme index 434d561..07cd6fc 100644 --- a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme +++ b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -39,17 +48,6 @@ - - - - - - - - Date: Sat, 29 Feb 2020 18:16:46 +0000 Subject: [PATCH 59/71] feat: migrate to swift package manager --- .gitignore | 2 + Configurations/LICENSE | 22 - .../UniversalFramework_Base.xcconfig | 25 - .../UniversalFramework_Framework.xcconfig | 32 -- .../UniversalFramework_Test.xcconfig | 18 - Package.swift | 13 + QueryKit.podspec | 2 +- QueryKit.xcodeproj/project.pbxproj | 471 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/QueryKit.xcscheme | 95 ---- QueryKit/Info.plist | 28 -- QueryKitTests/Info.plist | 24 - .../QueryKit}/Attribute.swift | 0 .../QueryKit}/Expression.swift | 0 .../QueryKit}/Predicate.swift | 0 {QueryKit => Sources/QueryKit}/QueryKit.h | 0 {QueryKit => Sources/QueryKit}/QuerySet.swift | 8 +- .../QueryKit}/SortDescriptor.swift | 0 .../QueryKitTests}/AttributeTests.swift | 0 .../QueryKitTests}/ExpressionTests.swift | 0 .../QueryKitTests}/PredicateTests.swift | 0 .../QueryKitTests}/QueryKitTests.swift | 0 .../QueryKitTests}/QuerySetTests.swift | 2 +- .../QueryKitTests}/SortDescriptorTests.swift | 0 24 files changed, 24 insertions(+), 725 deletions(-) delete mode 100644 Configurations/LICENSE delete mode 100644 Configurations/UniversalFramework_Base.xcconfig delete mode 100644 Configurations/UniversalFramework_Framework.xcconfig delete mode 100644 Configurations/UniversalFramework_Test.xcconfig create mode 100644 Package.swift delete mode 100644 QueryKit.xcodeproj/project.pbxproj delete mode 100644 QueryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme delete mode 100644 QueryKit/Info.plist delete mode 100644 QueryKitTests/Info.plist rename {QueryKit => Sources/QueryKit}/Attribute.swift (100%) rename {QueryKit => Sources/QueryKit}/Expression.swift (100%) rename {QueryKit => Sources/QueryKit}/Predicate.swift (100%) rename {QueryKit => Sources/QueryKit}/QueryKit.h (100%) rename {QueryKit => Sources/QueryKit}/QuerySet.swift (97%) rename {QueryKit => Sources/QueryKit}/SortDescriptor.swift (100%) rename {QueryKitTests => Tests/QueryKitTests}/AttributeTests.swift (100%) rename {QueryKitTests => Tests/QueryKitTests}/ExpressionTests.swift (100%) rename {QueryKitTests => Tests/QueryKitTests}/PredicateTests.swift (100%) rename {QueryKitTests => Tests/QueryKitTests}/QueryKitTests.swift (100%) rename {QueryKitTests => Tests/QueryKitTests}/QuerySetTests.swift (98%) rename {QueryKitTests => Tests/QueryKitTests}/SortDescriptorTests.swift (100%) diff --git a/.gitignore b/.gitignore index 47042c2..b69aff0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .DS_Store xcuserdata +*.xcodeproj/ +.build/ diff --git a/Configurations/LICENSE b/Configurations/LICENSE deleted file mode 100644 index ad21101..0000000 --- a/Configurations/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Marius Rackwitz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/Configurations/UniversalFramework_Base.xcconfig b/Configurations/UniversalFramework_Base.xcconfig deleted file mode 100644 index 261e2b2..0000000 --- a/Configurations/UniversalFramework_Base.xcconfig +++ /dev/null @@ -1,25 +0,0 @@ -// -// Put this file alongside to the other both, as it contains what -// both have in common. Don't rename this file. -// -// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. -// - -// Make it universal -SUPPORTED_PLATFORMS = macosx iphonesimulator iphoneos watchos watchsimulator appletvos appletvsimulator -VALID_ARCHS[sdk=macosx*] = i386 x86_64 -VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s -VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 -VALID_ARCHS[sdk=watchos*] = armv7k -VALID_ARCHS[sdk=watchsimulator*] = i386 -VALID_ARCHS[sdk=appletv*] = arm64 -VALID_ARCHS[sdk=appletvsimulator*] = x86_64 - -// Dynamic linking uses different default copy paths -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/Configurations/UniversalFramework_Framework.xcconfig b/Configurations/UniversalFramework_Framework.xcconfig deleted file mode 100644 index 1406c7a..0000000 --- a/Configurations/UniversalFramework_Framework.xcconfig +++ /dev/null @@ -1,32 +0,0 @@ -// -// Inherit from this config in your framework target. -// -// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. -// - -#include "UniversalFramework_Base.xcconfig" - -// OSX-specific default settings -FRAMEWORK_VERSION[sdk=macosx*] = A -COMBINE_HIDPI_IMAGES[sdk=macosx*] = YES - -// iOS-specific default settings -CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer -TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*] = 1,2 -TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2 - -// TV-specific default settings -TARGETED_DEVICE_FAMILY[sdk=appletvsimulator*] = 3 -TARGETED_DEVICE_FAMILY[sdk=appletv*] = 3 - -// Watch-specific default settings -TARGETED_DEVICE_FAMILY[sdk=watchsimulator*] = 4 -TARGETED_DEVICE_FAMILY[sdk=watch*] = 4 - -ENABLE_BITCODE[sdk=macosx*] = NO -ENABLE_BITCODE[sdk=watchsimulator*] = YES -ENABLE_BITCODE[sdk=watch*] = YES -ENABLE_BITCODE[sdk=iphonesimulator*] = YES -ENABLE_BITCODE[sdk=iphone*] = YES -ENABLE_BITCODE[sdk=appletvsimulator*] = YES -ENABLE_BITCODE[sdk=appletv*] = YES diff --git a/Configurations/UniversalFramework_Test.xcconfig b/Configurations/UniversalFramework_Test.xcconfig deleted file mode 100644 index 0c5f845..0000000 --- a/Configurations/UniversalFramework_Test.xcconfig +++ /dev/null @@ -1,18 +0,0 @@ -// -// Inherit from this config in the test target for your framework. -// -// Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. -// - -#include "UniversalFramework_Base.xcconfig" - -FRAMEWORK_SEARCH_PATHS = $(inherited) '$(PLATFORM_DIR)/Developer/Library/Frameworks' - -// Yep. -LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' -LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..d661163 --- /dev/null +++ b/Package.swift @@ -0,0 +1,13 @@ +// swift-tools-version:5.0 +import PackageDescription + + +let package = Package( + name: "QueryKit", + products: [ + ], + targets: [ + .target(name: "QueryKit", dependencies: []), + .testTarget(name: "QueryKitTests", dependencies: ["QueryKit"]), + ] +) diff --git a/QueryKit.podspec b/QueryKit.podspec index 07d46a1..26b43ea 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -14,6 +14,6 @@ Pod::Spec.new do |spec| spec.watchos.deployment_target = '2.0' spec.tvos.deployment_target = '9.0' spec.frameworks = 'CoreData' - spec.source_files = 'QueryKit/*.swift' + spec.source_files = 'Sources/QueryKit/*.swift' end diff --git a/QueryKit.xcodeproj/project.pbxproj b/QueryKit.xcodeproj/project.pbxproj deleted file mode 100644 index 4a045db..0000000 --- a/QueryKit.xcodeproj/project.pbxproj +++ /dev/null @@ -1,471 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 279ED5841BED09EB0011CA09 /* QueryKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 279ED5831BED09EB0011CA09 /* QueryKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 279ED58B1BED09EB0011CA09 /* QueryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 279ED5801BED09EB0011CA09 /* QueryKit.framework */; }; - 279ED5901BED09EB0011CA09 /* QueryKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */; }; - 279ED59F1BED0A5C0011CA09 /* SortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */; }; - 279ED5A01BED0A5C0011CA09 /* QuerySet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */; }; - 279ED5A11BED0A5C0011CA09 /* Predicate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59C1BED0A5C0011CA09 /* Predicate.swift */; }; - 279ED5A21BED0A5C0011CA09 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59D1BED0A5C0011CA09 /* Expression.swift */; }; - 279ED5A31BED0A5C0011CA09 /* Attribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279ED59E1BED0A5C0011CA09 /* Attribute.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 279ED58C1BED09EB0011CA09 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 279ED5771BED09EB0011CA09 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 279ED57F1BED09EB0011CA09; - remoteInfo = QueryKit; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 279ED5801BED09EB0011CA09 /* QueryKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = QueryKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 279ED5831BED09EB0011CA09 /* QueryKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QueryKit.h; sourceTree = ""; }; - 279ED5851BED09EB0011CA09 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QueryKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryKitTests.swift; sourceTree = ""; }; - 279ED5911BED09EB0011CA09 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortDescriptor.swift; sourceTree = ""; }; - 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuerySet.swift; sourceTree = ""; }; - 279ED59C1BED0A5C0011CA09 /* Predicate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Predicate.swift; sourceTree = ""; }; - 279ED59D1BED0A5C0011CA09 /* Expression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expression.swift; sourceTree = ""; }; - 279ED59E1BED0A5C0011CA09 /* Attribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Attribute.swift; sourceTree = ""; }; - 279ED5A61BED0AA50011CA09 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; - 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; - 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 279ED57C1BED09EB0011CA09 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 279ED5871BED09EB0011CA09 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 279ED58B1BED09EB0011CA09 /* QueryKit.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 279ED5761BED09EB0011CA09 = { - isa = PBXGroup; - children = ( - 279ED5A41BED0AA50011CA09 /* Configurations */, - 279ED5821BED09EB0011CA09 /* QueryKit */, - 279ED58E1BED09EB0011CA09 /* QueryKitTests */, - 279ED5811BED09EB0011CA09 /* Products */, - ); - sourceTree = ""; - }; - 279ED5811BED09EB0011CA09 /* Products */ = { - isa = PBXGroup; - children = ( - 279ED5801BED09EB0011CA09 /* QueryKit.framework */, - 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 279ED5821BED09EB0011CA09 /* QueryKit */ = { - isa = PBXGroup; - children = ( - 279ED5831BED09EB0011CA09 /* QueryKit.h */, - 279ED59B1BED0A5C0011CA09 /* QuerySet.swift */, - 279ED59E1BED0A5C0011CA09 /* Attribute.swift */, - 279ED59D1BED0A5C0011CA09 /* Expression.swift */, - 279ED59A1BED0A5C0011CA09 /* SortDescriptor.swift */, - 279ED59C1BED0A5C0011CA09 /* Predicate.swift */, - 279ED5851BED09EB0011CA09 /* Info.plist */, - ); - path = QueryKit; - sourceTree = ""; - }; - 279ED58E1BED09EB0011CA09 /* QueryKitTests */ = { - isa = PBXGroup; - children = ( - 279ED58F1BED09EB0011CA09 /* QueryKitTests.swift */, - 279ED5911BED09EB0011CA09 /* Info.plist */, - ); - path = QueryKitTests; - sourceTree = ""; - }; - 279ED5A41BED0AA50011CA09 /* Configurations */ = { - isa = PBXGroup; - children = ( - 279ED5A61BED0AA50011CA09 /* UniversalFramework_Base.xcconfig */, - 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */, - 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */, - ); - path = Configurations; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 279ED57D1BED09EB0011CA09 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 279ED5841BED09EB0011CA09 /* QueryKit.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 279ED57F1BED09EB0011CA09 /* QueryKit */ = { - isa = PBXNativeTarget; - buildConfigurationList = 279ED5941BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKit" */; - buildPhases = ( - 279ED57B1BED09EB0011CA09 /* Sources */, - 279ED57C1BED09EB0011CA09 /* Frameworks */, - 279ED57D1BED09EB0011CA09 /* Headers */, - 279ED57E1BED09EB0011CA09 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = QueryKit; - productName = QueryKit; - productReference = 279ED5801BED09EB0011CA09 /* QueryKit.framework */; - productType = "com.apple.product-type.framework"; - }; - 279ED5891BED09EB0011CA09 /* QueryKitTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 279ED5971BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKitTests" */; - buildPhases = ( - 279ED5861BED09EB0011CA09 /* Sources */, - 279ED5871BED09EB0011CA09 /* Frameworks */, - 279ED5881BED09EB0011CA09 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 279ED58D1BED09EB0011CA09 /* PBXTargetDependency */, - ); - name = QueryKitTests; - productName = QueryKitTests; - productReference = 279ED58A1BED09EB0011CA09 /* QueryKitTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 279ED5771BED09EB0011CA09 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 1130; - ORGANIZATIONNAME = QueryKit; - TargetAttributes = { - 279ED57F1BED09EB0011CA09 = { - CreatedOnToolsVersion = 7.1; - LastSwiftMigration = 0800; - }; - 279ED5891BED09EB0011CA09 = { - CreatedOnToolsVersion = 7.1; - LastSwiftMigration = 0800; - }; - }; - }; - buildConfigurationList = 279ED57A1BED09EB0011CA09 /* Build configuration list for PBXProject "QueryKit" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 279ED5761BED09EB0011CA09; - productRefGroup = 279ED5811BED09EB0011CA09 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 279ED57F1BED09EB0011CA09 /* QueryKit */, - 279ED5891BED09EB0011CA09 /* QueryKitTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 279ED57E1BED09EB0011CA09 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 279ED5881BED09EB0011CA09 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 279ED57B1BED09EB0011CA09 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 279ED5A31BED0A5C0011CA09 /* Attribute.swift in Sources */, - 279ED59F1BED0A5C0011CA09 /* SortDescriptor.swift in Sources */, - 279ED5A11BED0A5C0011CA09 /* Predicate.swift in Sources */, - 279ED5A01BED0A5C0011CA09 /* QuerySet.swift in Sources */, - 279ED5A21BED0A5C0011CA09 /* Expression.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 279ED5861BED09EB0011CA09 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 279ED5901BED09EB0011CA09 /* QueryKitTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 279ED58D1BED09EB0011CA09 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 279ED57F1BED09EB0011CA09 /* QueryKit */; - targetProxy = 279ED58C1BED09EB0011CA09 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 279ED5921BED09EB0011CA09 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 9.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Debug; - }; - 279ED5931BED09EB0011CA09 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.11; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 9.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 2.0; - }; - name = Release; - }; - 279ED5951BED09EB0011CA09 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = QueryKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 279ED5961BED09EB0011CA09 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 279ED5A71BED0AA50011CA09 /* UniversalFramework_Framework.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = ""; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = QueryKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKit; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 279ED5981BED09EB0011CA09 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QueryKitTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 279ED5991BED09EB0011CA09 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 279ED5A81BED0AA50011CA09 /* UniversalFramework_Test.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = QueryKitTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.querykit.QueryKitTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 279ED57A1BED09EB0011CA09 /* Build configuration list for PBXProject "QueryKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279ED5921BED09EB0011CA09 /* Debug */, - 279ED5931BED09EB0011CA09 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 279ED5941BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKit" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279ED5951BED09EB0011CA09 /* Debug */, - 279ED5961BED09EB0011CA09 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 279ED5971BED09EB0011CA09 /* Build configuration list for PBXNativeTarget "QueryKitTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 279ED5981BED09EB0011CA09 /* Debug */, - 279ED5991BED09EB0011CA09 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 279ED5771BED09EB0011CA09 /* Project object */; -} diff --git a/QueryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/QueryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1639ef8..0000000 --- a/QueryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme b/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme deleted file mode 100644 index 07cd6fc..0000000 --- a/QueryKit.xcodeproj/xcshareddata/xcschemes/QueryKit.xcscheme +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/QueryKit/Info.plist b/QueryKit/Info.plist deleted file mode 100644 index f2e8865..0000000 --- a/QueryKit/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - NSHumanReadableCopyright - Copyright © 2015 QueryKit. All rights reserved. - NSPrincipalClass - - - diff --git a/QueryKitTests/Info.plist b/QueryKitTests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/QueryKitTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/QueryKit/Attribute.swift b/Sources/QueryKit/Attribute.swift similarity index 100% rename from QueryKit/Attribute.swift rename to Sources/QueryKit/Attribute.swift diff --git a/QueryKit/Expression.swift b/Sources/QueryKit/Expression.swift similarity index 100% rename from QueryKit/Expression.swift rename to Sources/QueryKit/Expression.swift diff --git a/QueryKit/Predicate.swift b/Sources/QueryKit/Predicate.swift similarity index 100% rename from QueryKit/Predicate.swift rename to Sources/QueryKit/Predicate.swift diff --git a/QueryKit/QueryKit.h b/Sources/QueryKit/QueryKit.h similarity index 100% rename from QueryKit/QueryKit.h rename to Sources/QueryKit/QueryKit.h diff --git a/QueryKit/QuerySet.swift b/Sources/QueryKit/QuerySet.swift similarity index 97% rename from QueryKit/QuerySet.swift rename to Sources/QueryKit/QuerySet.swift index c1f0ccd..8fa51d6 100644 --- a/QueryKit/QuerySet.swift +++ b/Sources/QueryKit/QuerySet.swift @@ -140,7 +140,13 @@ extension QuerySet { return items.first } - public subscript(range:Range) -> QuerySet { + public subscript(range: ClosedRange) -> QuerySet { + get { + return self[Range(range)] + } + } + + public subscript(range: Range) -> QuerySet { get { var fullRange = range diff --git a/QueryKit/SortDescriptor.swift b/Sources/QueryKit/SortDescriptor.swift similarity index 100% rename from QueryKit/SortDescriptor.swift rename to Sources/QueryKit/SortDescriptor.swift diff --git a/QueryKitTests/AttributeTests.swift b/Tests/QueryKitTests/AttributeTests.swift similarity index 100% rename from QueryKitTests/AttributeTests.swift rename to Tests/QueryKitTests/AttributeTests.swift diff --git a/QueryKitTests/ExpressionTests.swift b/Tests/QueryKitTests/ExpressionTests.swift similarity index 100% rename from QueryKitTests/ExpressionTests.swift rename to Tests/QueryKitTests/ExpressionTests.swift diff --git a/QueryKitTests/PredicateTests.swift b/Tests/QueryKitTests/PredicateTests.swift similarity index 100% rename from QueryKitTests/PredicateTests.swift rename to Tests/QueryKitTests/PredicateTests.swift diff --git a/QueryKitTests/QueryKitTests.swift b/Tests/QueryKitTests/QueryKitTests.swift similarity index 100% rename from QueryKitTests/QueryKitTests.swift rename to Tests/QueryKitTests/QueryKitTests.swift diff --git a/QueryKitTests/QuerySetTests.swift b/Tests/QueryKitTests/QuerySetTests.swift similarity index 98% rename from QueryKitTests/QuerySetTests.swift rename to Tests/QueryKitTests/QuerySetTests.swift index d1dbc3b..0653a5a 100644 --- a/QueryKitTests/QuerySetTests.swift +++ b/Tests/QueryKitTests/QuerySetTests.swift @@ -63,7 +63,7 @@ class QuerySetTests: XCTestCase { func testTypeSafeOrderBySortDescriptors() { let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) - let qs = queryset.orderBy { [$0.name.ascending()] } + let qs = queryset.orderBy { [$0.name.ascending() as SortDescriptor] } XCTAssertTrue(qs.sortDescriptors == [sortDescriptor]) } diff --git a/QueryKitTests/SortDescriptorTests.swift b/Tests/QueryKitTests/SortDescriptorTests.swift similarity index 100% rename from QueryKitTests/SortDescriptorTests.swift rename to Tests/QueryKitTests/SortDescriptorTests.swift From 65db604fa075004be51bdcd390a1df432180d966 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 14:01:06 +0000 Subject: [PATCH 60/71] chore: switch to GitHub actions --- .github/workflows/main.yaml | 7 +++++++ .travis.yml | 7 ------- README.md | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/main.yaml delete mode 100644 .travis.yml diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..9ede81c --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,7 @@ +on: push +jobs: + test: + runs-on: macos-latest + steps: + - uses: actions/checkout@v1 + - run: swift test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d1e7a88..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: objective-c -osx_image: xcode7.1 -script: - - set -o pipefail - - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk macosx | xcpretty -c - - xcodebuild -project QueryKit.xcodeproj -scheme QueryKit test -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c - - pod lib lint --allow-warnings --quick diff --git a/README.md b/README.md index c7ca46c..69f0960 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ # QueryKit -[![Build Status](http://img.shields.io/travis/QueryKit/QueryKit/master.svg?style=flat)](https://travis-ci.org/QueryKit/QueryKit) - QueryKit, a simple type-safe Core Data query language. ## Usage From 0546e7e970eb0e6234cb9f47b6838d5e6b28d5f2 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 13:34:03 +0000 Subject: [PATCH 61/71] feat: support KeyPath predicates --- Sources/QueryKit/KeyPath.swift | 86 ++++++++++++++++++ Tests/QueryKitTests/KeyPathTests.swift | 121 +++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 Sources/QueryKit/KeyPath.swift create mode 100644 Tests/QueryKitTests/KeyPathTests.swift diff --git a/Sources/QueryKit/KeyPath.swift b/Sources/QueryKit/KeyPath.swift new file mode 100644 index 0000000..f55733d --- /dev/null +++ b/Sources/QueryKit/KeyPath.swift @@ -0,0 +1,86 @@ +import CoreData + +// MARK: Predicate + +public func == (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs == rhs) +} + +public func != (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs != rhs) +} + +public func > (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs > rhs) +} + +public func >= (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs >= rhs) +} + +public func < (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs < rhs) +} + +public func <= (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs <= rhs) +} + +public func ~= (lhs: KeyPath, rhs: V) -> Predicate { + return Predicate(predicate: lhs ~= rhs) +} + +public func << (lhs: KeyPath, rhs: [V]) -> Predicate { + return Predicate(predicate: lhs << rhs) +} + +public func << (lhs: KeyPath, rhs: Range) -> Predicate { + return Predicate(predicate: lhs << rhs) +} + +// MARK: - NSPredicate + +public func == (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute == rhs +} + +public func != (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute != rhs +} + +public func > (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute > rhs +} + +public func >= (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute >= rhs +} + +public func < (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute < rhs +} + +public func <= (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute <= rhs +} + +public func ~= (lhs: KeyPath, rhs: V) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute ~= rhs +} + +public func << (lhs: KeyPath, rhs: [V]) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute << rhs +} + +public func << (lhs: KeyPath, rhs: Range) -> NSPredicate { + let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) + return attribute << rhs +} diff --git a/Tests/QueryKitTests/KeyPathTests.swift b/Tests/QueryKitTests/KeyPathTests.swift new file mode 100644 index 0000000..1bef2f5 --- /dev/null +++ b/Tests/QueryKitTests/KeyPathTests.swift @@ -0,0 +1,121 @@ +import XCTest +@testable import QueryKit + +class KeyPathTests: XCTestCase { + func testEqualityOperator() { + let predicate: Predicate = \User.name == "kyle" + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == 'kyle'")) + } + + func testEqualityOperatorWithOptional() { + let predicate: Predicate = \User.name == nil + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == %@", NSNull())) + } + + func testInequalityOperator() { + let predicate: Predicate = \User.name != "kyle" + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name != 'kyle'")) + } + + func testInqqualityOperatorWithOptional() { + let predicate: Predicate = \User.name != nil + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name != %@", NSNull())) + } + + func testGreaterThanOperator() { + let predicate: Predicate = \User.age > 17 + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age > 17")) + } + + func testGreaterThanOrEqualOperator() { + let predicate: Predicate = \User.age >= 18 + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age >= 18")) + } + + func testLessThanOperator() { + let predicate: Predicate = \User.age < 18 + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age < 18")) + } + + func testLessThanOrEqualOperator() { + let predicate: Predicate = \User.age <= 17 + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age <= 17")) + } + + func testLikeOperator() { + let predicate: Predicate = \User.name ~= "k*" + XCTAssertEqual(predicate.predicate, NSPredicate(format:"name LIKE 'k*'")) + } + + func testInOperator() { + let predicate: Predicate = \User.age << [5, 10] + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age IN %@", [5, 10])) + } + + func testBetweenRangeOperator() { + let predicate: Predicate = \User.age << (32 ..< 64) + XCTAssertEqual(predicate.predicate, NSPredicate(format:"age BETWEEN %@", [32, 64])) + } +} + +class KeyPathNSPredicateTests: XCTestCase { + func testEqualityOperator() { + let predicate: NSPredicate = \User.name == "kyle" + XCTAssertEqual(predicate, NSPredicate(format:"name == 'kyle'")) + } + + func testEqualityOperatorWithOptional() { + let predicate: NSPredicate = \User.name == nil + XCTAssertEqual(predicate, NSPredicate(format:"name == %@", NSNull())) + } + + func testInequalityOperator() { + let predicate: NSPredicate = \User.name != "kyle" + XCTAssertEqual(predicate, NSPredicate(format:"name != 'kyle'")) + } + + func testInqqualityOperatorWithOptional() { + let predicate: NSPredicate = \User.name != nil + XCTAssertEqual(predicate, NSPredicate(format:"name != %@", NSNull())) + } + + func testGreaterThanOperator() { + let predicate: NSPredicate = \User.age > 17 + XCTAssertEqual(predicate, NSPredicate(format:"age > 17")) + } + + func testGreaterThanOrEqualOperator() { + let predicate: NSPredicate = \User.age >= 18 + XCTAssertEqual(predicate, NSPredicate(format:"age >= 18")) + } + + func testLessThanOperator() { + let predicate: NSPredicate = \User.age < 18 + XCTAssertEqual(predicate, NSPredicate(format:"age < 18")) + } + + func testLessThanOrEqualOperator() { + let predicate: NSPredicate = \User.age <= 17 + XCTAssertEqual(predicate, NSPredicate(format:"age <= 17")) + } + + func testLikeOperator() { + let predicate: NSPredicate = \User.name ~= "k*" + XCTAssertEqual(predicate, NSPredicate(format:"name LIKE 'k*'")) + } + + func testInOperator() { + let predicate: NSPredicate = \User.age << [5, 10] + XCTAssertEqual(predicate, NSPredicate(format:"age IN %@", [5, 10])) + } + + func testBetweenRangeOperator() { + let predicate: NSPredicate = \User.age << (32 ..< 64) + XCTAssertEqual(predicate, NSPredicate(format:"age BETWEEN %@", [32, 64])) + } +} + +class User: NSManagedObject { + @objc var name: String? + @NSManaged var age: Int +} From a3df08fb2b1c6b39abc0c0533e494ca1f5234c15 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 13:39:44 +0000 Subject: [PATCH 62/71] feat: support KeyPath ordering --- Sources/QueryKit/QuerySet.swift | 5 +++++ Tests/QueryKitTests/QuerySetTests.swift | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Sources/QueryKit/QuerySet.swift b/Sources/QueryKit/QuerySet.swift index 8fa51d6..9d057c1 100644 --- a/Sources/QueryKit/QuerySet.swift +++ b/Sources/QueryKit/QuerySet.swift @@ -63,6 +63,11 @@ extension QuerySet { // MARK: Type-safe Sorting + /// Returns a new QuerySet containing objects ordered by the given key path. + public func orderBy(_ keyPath: KeyPath, ascending: Bool) -> QuerySet { + return orderBy(NSSortDescriptor(key: (keyPath as AnyKeyPath)._kvcKeyPathString!, ascending: ascending)) + } + /// Returns a new QuerySet containing objects ordered by the given sort descriptor. public func orderBy(_ closure:((ModelType.Type) -> (SortDescriptor))) -> QuerySet { return orderBy(closure(ModelType.self).sortDescriptor) diff --git a/Tests/QueryKitTests/QuerySetTests.swift b/Tests/QueryKitTests/QuerySetTests.swift index 0653a5a..6a73b2b 100644 --- a/Tests/QueryKitTests/QuerySetTests.swift +++ b/Tests/QueryKitTests/QuerySetTests.swift @@ -44,6 +44,22 @@ class QuerySetTests: XCTestCase { // MARK: Sorting + func testOrderByKeyPathAscending() { + let qs = queryset.orderBy(\.name, ascending: true) + + XCTAssertEqual(qs.sortDescriptors, [ + NSSortDescriptor(key: "name", ascending: true), + ]) + } + + func testOrderByKeyPathDecending() { + let qs = queryset.orderBy(\.name, ascending: false) + + XCTAssertEqual(qs.sortDescriptors, [ + NSSortDescriptor(key: "name", ascending: false), + ]) + } + func testOrderBySortDescriptor() { let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) let qs = queryset.orderBy(sortDescriptor) From 4530948193c0967f3e1c6aeaeba57e0b1834848b Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 13:44:59 +0000 Subject: [PATCH 63/71] feat: support KeyPath filter/exclude --- Sources/QueryKit/Attribute.swift | 4 ++-- Sources/QueryKit/QuerySet.swift | 10 ++++++++++ Tests/QueryKitTests/QuerySetTests.swift | 10 ++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Sources/QueryKit/Attribute.swift b/Sources/QueryKit/Attribute.swift index 078707b..ecdf487 100644 --- a/Sources/QueryKit/Attribute.swift +++ b/Sources/QueryKit/Attribute.swift @@ -112,11 +112,11 @@ prefix public func ! (left: Attribute) -> NSPredicate { public extension QuerySet { func filter(_ attribute:Attribute) -> QuerySet { - return filter(attribute == true) + return filter((attribute == true) as NSPredicate) } func exclude(_ attribute:Attribute) -> QuerySet { - return filter(attribute == false) + return filter((attribute == false) as NSPredicate) } } diff --git a/Sources/QueryKit/QuerySet.swift b/Sources/QueryKit/QuerySet.swift index 9d057c1..6f85230 100644 --- a/Sources/QueryKit/QuerySet.swift +++ b/Sources/QueryKit/QuerySet.swift @@ -80,6 +80,11 @@ extension QuerySet { // MARK: Filtering + /// Returns a new QuerySet containing objects that match the given predicate. + public func filter(_ predicate: Predicate) -> QuerySet { + return filter(predicate.predicate) + } + /// Returns a new QuerySet containing objects that match the given predicate. public func filter(_ predicate:NSPredicate) -> QuerySet { var futurePredicate = predicate @@ -97,6 +102,11 @@ extension QuerySet { return filter(newPredicate) } + /// Returns a new QuerySet containing objects that exclude the given predicate. + public func exclude(_ predicate: Predicate) -> QuerySet { + return exclude(predicate.predicate) + } + /// Returns a new QuerySet containing objects that exclude the given predicate. public func exclude(_ predicate:NSPredicate) -> QuerySet { let excludePredicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.not, subpredicates: [predicate]) diff --git a/Tests/QueryKitTests/QuerySetTests.swift b/Tests/QueryKitTests/QuerySetTests.swift index 6a73b2b..5ecab25 100644 --- a/Tests/QueryKitTests/QuerySetTests.swift +++ b/Tests/QueryKitTests/QuerySetTests.swift @@ -96,6 +96,11 @@ class QuerySetTests: XCTestCase { // MARK: Filtering + func testFilterKeyPath() { + let qs = queryset.filter(\.name == "Kyle") + XCTAssertEqual(qs.predicate?.description, "name == \"Kyle\"") + } + func testFilterPredicate() { let predicate = NSPredicate(format: "name == Kyle") let qs = queryset.filter(predicate) @@ -136,6 +141,11 @@ class QuerySetTests: XCTestCase { // MARK: Exclusion + func testExcludeKeyPath() { + let qs = queryset.exclude(\.name == "Kyle") + XCTAssertEqual(qs.predicate?.description, "NOT name == \"Kyle\"") + } + func testExcludePredicate() { let predicate = NSPredicate(format: "name == Kyle") let qs = queryset.exclude(predicate) From 7934e49b5c0cfb1382588752f1ea75735a4bd16b Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 13:57:26 +0000 Subject: [PATCH 64/71] docs: update documentation for KeyPath --- CHANGELOG.md | 15 ++++++++++ README.md | 84 ++++++++++++++++------------------------------------ 2 files changed, 41 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4638af..2fb1ba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,3 +5,18 @@ ### Breaking * Drops support for Swift 3 and Swift 4. Swift 5 or newer must be used. + +### Enhancements + +* Added support for ordering by Swift KeyPath, for example: + + ```swift + queryset.orderBy(\.createdAt, ascending: true) + ``` + +* Added support for filtering and excluding by Swift KeyPath, for example: + + ```swift + queryset.exclude(\.name == "Kyle") + queryset.filter(\.createdAt > Date()) + ``` diff --git a/README.md b/README.md index 69f0960..2cc9993 100644 --- a/README.md +++ b/README.md @@ -6,29 +6,10 @@ QueryKit, a simple type-safe Core Data query language. ## Usage -To get the most out of QueryKit, and to get full type-safe queries, you may -add extensions for your Core Data models providing properties which describe -your models. You may use [querykit-cli](https://github.com/QueryKit/querykit-cli) -to generate these automatically. - -An extension for our a `Person` model might look as follows: - -```swift -extension User { - static var name:Attribute { return Attribute("name") } - static var age:Attribute { return Attribute("age") } -} -``` - -This provides static properties on our User model which represent each property -on our Core Data model, these may be used to construct predicates and sort -descriptors with compile time safety, without stringly typing them -into your application. - ```swift -let namePredicate = Person.name == "Kyle" -let agePredicate = Person.age > 25 -let ageSortDescriptor = Person.age.descending() +QuerySet(context, "Person") + .orderedBy(.name, ascending: true) + .filter(\.age >= 18) ``` ### QuerySet @@ -40,20 +21,19 @@ results based on the given parameters. #### Retrieving all objects ```swift -let queryset = Person.queryset(context) +let queryset = QuerySet(context, "Person") ``` #### Retrieving specific objects with filters You may filter a QuerySet using the `filter` and `exclude` methods, which -accept a closure passing the model type allowing you to access the -type-safe attributes. +accept a predicate which can be constructed using KeyPath extensions. -The `filter` and `exclude` methods return brand new QuerySet's including your filter. +The `filter` and `exclude` methods return new QuerySet's including your filter. ```swift -queryset.filter { $0.name == "Kyle" } -queryset.exclude { $0.age > 25 } +queryset.filter(\.name == "Kyle") +queryset.exclude(\.age > 25) ``` You may also use standard `NSPredicate` if you want to construct complicated @@ -70,14 +50,13 @@ The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example: ```swift -queryset.filter { $0.name == "Kyle" } - .exclude { $0.age < 25 } - .filter { $0.isEmployed } +queryset.filter(\.name == "Kyle") + .exclude(\.age < 25) ``` -Each time you refine a QuerySet, you get a brand-new QuerySet that is in -no way bound to the previous QuerySet. Each refinement creates a separate -and distinct QuerySet that may be stored, used and reused. +Each time you refine a QuerySet, you get a new QuerySet instance that is in no +way bound to the previous QuerySet. Each refinement creates a separate and +distinct QuerySet that may be stored, used and reused. #### QuerySets are lazy @@ -88,17 +67,15 @@ QuerySet is *evaluated*. #### Ordering You may order a QuerySet's results by using the `orderBy` function which -accepts a closure passing the model type, and expects a sort descriptor in -return. +accepts a KeyPath. ```swift -queryset.orderBy { $0.name.ascending() } +queryset.orderBy(\.name, ascending: true) ``` You may also pass in an `NSSortDescriptor` if you would rather. ```swift -queryset.orderBy(Person.name.ascending()) queryset.orderBy(NSSortDescriptor(key: "name", ascending: true)) ``` @@ -108,7 +85,7 @@ Using slicing, a QuerySet's results may be limited to a specified range. For example, to get the first 5 items in our QuerySet: ```swift -queryset[0..5] +queryset[0...5] ``` **NOTE**: *Remember, QuerySets are lazily evaluated. Slicing doesn’t evaluate the query.* @@ -158,35 +135,26 @@ count or an error if the operation failed. let deleted = try? queryset.delete() ``` -#### Attribute - -The `Attribute` is a generic structure for creating predicates in a -type-safe manner as shown at the start of the README. - -```swift -let name = Attribute("name") -let age = Attribute("age") -``` - ##### Operators -QueryKit provides custom operator functions allowing you to create predicates. +QueryKit provides KeyPath extensions providing operator functions allowing you +to create predicates. ```swift // Name is equal to Kyle -name == "Kyle" +\Person.name == "Kyle" // Name is either equal to Kyle or Katie -name << ["Kyle", "Katie"] +\.Person.name << ["Kyle", "Katie"] // Age is equal to 27 -age == 27 +\.Person.age == 27 // Age is more than or equal to 25 -age >= 25 +\Person.age >= 25 // Age is within the range 22 to 30. -age << (22...30) +\Person.age << (22...30) ``` The following types of comparisons are supported using Attribute: @@ -210,13 +178,13 @@ QueryKit provides the `!`, `&&` and `||` operators for joining multiple predicat ```swift // Persons name is Kyle or Katie -Person.name == "Kyle" || Person.name == "Katie" +\Person.name == "Kyle" || \Person.name == "Katie" // Persons age is more than 25 and their name is Kyle -Person.age >= 25 && Person.name == "Kyle" +\Person.age >= 25 && \Person.name == "Kyle" // Persons name is not Kyle -!(Person.name == "Kyle") +!(\Person.name == "Kyle") ``` ## Installation From ca46aacab13be927d3a6266ed78c03306a9fc290 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 14:16:27 +0000 Subject: [PATCH 65/71] chore: deprecate attribute filtering/excluding This is replaced by KeyPath --- Sources/QueryKit/QuerySet.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/QueryKit/QuerySet.swift b/Sources/QueryKit/QuerySet.swift index 6f85230..a1603bb 100644 --- a/Sources/QueryKit/QuerySet.swift +++ b/Sources/QueryKit/QuerySet.swift @@ -122,21 +122,25 @@ extension QuerySet { // MARK: Type-safe filtering /// Returns a new QuerySet containing objects that match the given predicate. + @available(*, deprecated, renamed: "filter(_:)", message: "Replaced by KeyPath filtering https://git.io/Jv2v3") public func filter(_ closure:((ModelType.Type) -> (Predicate))) -> QuerySet { return filter(closure(ModelType.self).predicate) } /// Returns a new QuerySet containing objects that exclude the given predicate. + @available(*, deprecated, renamed: "exclude(_:)", message: "Replaced by KeyPath filtering https://git.io/Jv2v3") public func exclude(_ closure:((ModelType.Type) -> (Predicate))) -> QuerySet { return exclude(closure(ModelType.self).predicate) } /// Returns a new QuerySet containing objects that match the given predicatess. + @available(*, deprecated, renamed: "filter(_:)", message: "Replaced by KeyPath filtering https://git.io/Jv2v3") public func filter(_ closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { return filter(closures.map { $0(ModelType.self).predicate }) } /// Returns a new QuerySet containing objects that exclude the given predicates. + @available(*, deprecated, renamed: "exclude(_:)", message: "Replaced by KeyPath filtering https://git.io/Jv2v3") public func exclude(_ closures:[((ModelType.Type) -> (Predicate))]) -> QuerySet { return exclude(closures.map { $0(ModelType.self).predicate }) } From 815777df8d294447c4cbe946f250aa5fdb1e011d Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Sun, 1 Mar 2020 14:19:24 +0000 Subject: [PATCH 66/71] release: 0.14.0 --- QueryKit.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QueryKit.podspec b/QueryKit.podspec index 26b43ea..9111f55 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,8 +1,8 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.13.0' + spec.version = '0.14.0' spec.summary = 'A simple type-safe Core Data query language.' - spec.homepage = 'http://querykit.org/' + spec.homepage = 'https://github.com/QueryKit/QueryKit/' spec.license = { :type => 'BSD', :file => 'LICENSE' } spec.author = { 'Kyle Fuller' => 'kyle@fuller.li' } spec.social_media_url = 'https://twitter.com/QueryKit' From 5316d7b54d197d92a9f5af194454daf773a00fcf Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Tue, 3 Mar 2020 22:17:03 +0000 Subject: [PATCH 67/71] fix: support optional operators --- CHANGELOG.md | 6 ++++++ Sources/QueryKit/Attribute.swift | 5 +---- Tests/QueryKitTests/KeyPathTests.swift | 6 ++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fb1ba1..7614781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Master +### Bug Fixes + +* Prevents fatal error when handling operators with optional `Date` types. + +## 0.14.0 + ### Breaking * Drops support for Swift 3 and Swift 4. Swift 5 or newer must be used. diff --git a/Sources/QueryKit/Attribute.swift b/Sources/QueryKit/Attribute.swift index ecdf487..a917dec 100644 --- a/Sources/QueryKit/Attribute.swift +++ b/Sources/QueryKit/Attribute.swift @@ -43,10 +43,7 @@ public struct Attribute : Equatable { } } - let value = unsafeBitCast(value, to: Optional.self) - if let value = value { - return NSExpression(forConstantValue: value) - } + return NSExpression(forConstantValue: value) } return NSExpression(forConstantValue: NSNull()) diff --git a/Tests/QueryKitTests/KeyPathTests.swift b/Tests/QueryKitTests/KeyPathTests.swift index 1bef2f5..09d44b8 100644 --- a/Tests/QueryKitTests/KeyPathTests.swift +++ b/Tests/QueryKitTests/KeyPathTests.swift @@ -12,6 +12,11 @@ class KeyPathTests: XCTestCase { XCTAssertEqual(predicate.predicate, NSPredicate(format:"name == %@", NSNull())) } + func testOptionalEqualityOperatorWithOptional() { + let predicate: Predicate = \User.createdAt == nil + XCTAssertEqual(predicate.predicate, NSPredicate(format:"createdAt == %@", NSNull())) + } + func testInequalityOperator() { let predicate: Predicate = \User.name != "kyle" XCTAssertEqual(predicate.predicate, NSPredicate(format:"name != 'kyle'")) @@ -118,4 +123,5 @@ class KeyPathNSPredicateTests: XCTestCase { class User: NSManagedObject { @objc var name: String? @NSManaged var age: Int + @objc var createdAt: Date? } From 4ea1d9ca99edeba6a5ab144d4bfc346468b1eff9 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 9 Mar 2020 18:40:25 +0000 Subject: [PATCH 68/71] refactor: remove KeyPath dependency on Attribute --- Sources/QueryKit/KeyPath.swift | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Sources/QueryKit/KeyPath.swift b/Sources/QueryKit/KeyPath.swift index f55733d..8991eaa 100644 --- a/Sources/QueryKit/KeyPath.swift +++ b/Sources/QueryKit/KeyPath.swift @@ -1,5 +1,9 @@ import CoreData +func expression(for keyPath: KeyPath) -> NSExpression { + return NSExpression(forKeyPath: (keyPath as AnyKeyPath)._kvcKeyPathString!) +} + // MARK: Predicate public func == (lhs: KeyPath, rhs: V) -> Predicate { @@ -41,46 +45,37 @@ public func << (lhs: KeyPath, rhs: Range) -> Pr // MARK: - NSPredicate public func == (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute == rhs + return expression(for: lhs) == NSExpression(forConstantValue: rhs) } public func != (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute != rhs + return expression(for: lhs) != NSExpression(forConstantValue: rhs) } public func > (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute > rhs + return expression(for: lhs) > NSExpression(forConstantValue: rhs) } public func >= (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute >= rhs + return expression(for: lhs) >= NSExpression(forConstantValue: rhs) } public func < (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute < rhs + return expression(for: lhs) < NSExpression(forConstantValue: rhs) } public func <= (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute <= rhs + return expression(for: lhs) <= NSExpression(forConstantValue: rhs) } public func ~= (lhs: KeyPath, rhs: V) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute ~= rhs + return expression(for: lhs) ~= NSExpression(forConstantValue: rhs) } public func << (lhs: KeyPath, rhs: [V]) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute << rhs + return expression(for: lhs) << NSExpression(forConstantValue: rhs) } public func << (lhs: KeyPath, rhs: Range) -> NSPredicate { - let attribute = Attribute((lhs as AnyKeyPath)._kvcKeyPathString!) - return attribute << rhs + return expression(for: lhs) << NSExpression(forConstantValue: rhs) } From 9407c92c0089c45a085ac7b112e07b9ef511dc25 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Mon, 9 Mar 2020 18:40:33 +0000 Subject: [PATCH 69/71] release: 0.14.1 --- CHANGELOG.md | 2 +- QueryKit.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7614781..8001372 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # QueryKit Changelog -## Master +## 0.14.1 ### Bug Fixes diff --git a/QueryKit.podspec b/QueryKit.podspec index 9111f55..03c48fd 100644 --- a/QueryKit.podspec +++ b/QueryKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'QueryKit' - spec.version = '0.14.0' + spec.version = '0.14.1' spec.summary = 'A simple type-safe Core Data query language.' spec.homepage = 'https://github.com/QueryKit/QueryKit/' spec.license = { :type => 'BSD', :file => 'LICENSE' } From a4b9f07f461050287358f46811ebd3099e1d2629 Mon Sep 17 00:00:00 2001 From: mxgc <62173553+mxgc@users.noreply.github.com> Date: Mon, 25 May 2020 03:18:20 -0700 Subject: [PATCH 70/71] fix: add library product to Package.swift (#57) --- Package.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Package.swift b/Package.swift index d661163..ebd1d10 100644 --- a/Package.swift +++ b/Package.swift @@ -5,6 +5,7 @@ import PackageDescription let package = Package( name: "QueryKit", products: [ + .library(name: "QueryKit", targets: ["QueryKit"]), ], targets: [ .target(name: "QueryKit", dependencies: []), From 6542e1129885173d31cc6206855bd8abb52b446a Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Thu, 10 Jun 2021 18:26:06 +0100 Subject: [PATCH 71/71] perf: optimise queryset exists --- Sources/QueryKit/QuerySet.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/QueryKit/QuerySet.swift b/Sources/QueryKit/QuerySet.swift index a1603bb..c63d7a8 100644 --- a/Sources/QueryKit/QuerySet.swift +++ b/Sources/QueryKit/QuerySet.swift @@ -223,8 +223,11 @@ extension QuerySet { :note: Returns nil if the operation could not be completed. */ public func exists() throws -> Bool { - let result:Int = try count() - return result > 0 + let fetchRequest = self.fetchRequest + fetchRequest.fetchLimit = 1 + + let result = try context.count(for: fetchRequest) + return result != 0 } // MARK: Deletion