mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-16 14:06:53 +01:00
WIP: documentation
This commit is contained in:
@@ -2,8 +2,25 @@
|
||||
// AnyCoreStoreKeyPath.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Estropia on 2017/10/02.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -67,7 +67,18 @@ public extension CoreStore {
|
||||
return self.defaultStack.monitorList(from, fetchClauses)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
let monitor = CoreStore.monitorList(
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public static func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.defaultStack.monitorList(clauseChain.from, clauseChain.fetchClauses)
|
||||
@@ -97,7 +108,23 @@ public extension CoreStore {
|
||||
self.defaultStack.monitorList(createAsynchronously: createAsynchronously, from, fetchClauses)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||
|
||||
```
|
||||
CoreStore.monitorList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public static func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.defaultStack.monitorList(
|
||||
@@ -133,7 +160,19 @@ public extension CoreStore {
|
||||
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
let monitor = CoreStore.monitorSectionedList(
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public static func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.defaultStack.monitorSectionedList(
|
||||
@@ -169,7 +208,22 @@ public extension CoreStore {
|
||||
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
CoreStore.monitorSectionedList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public static func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.defaultStack.monitorSectionedList(
|
||||
|
||||
@@ -2,8 +2,25 @@
|
||||
// CoreStoreManagedObject.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Rommel Estropia on 2017/06/04.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
|
||||
@@ -88,7 +88,18 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses.
|
||||
```
|
||||
let monitor = dataStack.monitorList(
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorList(clauseChain.from, clauseChain.fetchClauses)
|
||||
@@ -136,7 +147,23 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||
|
||||
```
|
||||
dataStack.monitorList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public func monitorList<B: FetchChainableBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.monitorList(
|
||||
@@ -190,7 +217,19 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
let monitor = dataStack.monitorSectionedList(
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorSectionedList(
|
||||
@@ -245,7 +284,22 @@ public extension DataStack {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
dataStack.monitorSectionedList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.monitorSectionedList(
|
||||
|
||||
74
Sources/FetchChainBuilder.swift
Normal file
74
Sources/FetchChainBuilder.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// FetchChainBuilder.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - FetchChainBuilder
|
||||
|
||||
/**
|
||||
The fetch builder type used for fetches. A `FetchChainBuilder` is created from a `From` clause.
|
||||
```
|
||||
let people = source.fetchAll(
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
*/
|
||||
public struct FetchChainBuilder<D: DynamicObject>: FetchChainableBuilderType {
|
||||
|
||||
// MARK: FetchChainableBuilderType
|
||||
|
||||
public typealias ObjectType = D
|
||||
|
||||
public var from: From<D>
|
||||
public var fetchClauses: [FetchClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - FetchChainableBuilderType
|
||||
|
||||
/**
|
||||
Utility protocol for `FetchChainBuilder`. Used in fetch methods that support chained fetch builders.
|
||||
*/
|
||||
public protocol FetchChainableBuilderType {
|
||||
|
||||
/**
|
||||
The `DynamicObject` type for the fetch
|
||||
*/
|
||||
associatedtype ObjectType: DynamicObject
|
||||
|
||||
/**
|
||||
The `From` clause specifies the source entity and source persistent store for the fetch
|
||||
*/
|
||||
var from: From<ObjectType> { get set }
|
||||
|
||||
/**
|
||||
The `FetchClause`s to be used for the fetch
|
||||
*/
|
||||
var fetchClauses: [FetchClause] { get set }
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// FetchCondition.swift
|
||||
// From+Querying.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
@@ -27,85 +27,96 @@ import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - FetchChainableBuilderType
|
||||
|
||||
public protocol FetchChainableBuilderType {
|
||||
|
||||
associatedtype ObjectType: DynamicObject
|
||||
|
||||
var from: From<ObjectType> { get set }
|
||||
var fetchClauses: [FetchClause] { get set }
|
||||
}
|
||||
|
||||
|
||||
// MARK: - QueryChainableBuilderType
|
||||
|
||||
public protocol QueryChainableBuilderType {
|
||||
|
||||
associatedtype ObjectType: DynamicObject
|
||||
associatedtype ResultType: SelectResultType
|
||||
|
||||
var from: From<ObjectType> { get set }
|
||||
var select: Select<ObjectType, ResultType> { get set }
|
||||
var queryClauses: [QueryClause] { get set }
|
||||
}
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public protocol SectionMonitorBuilderType {
|
||||
|
||||
associatedtype ObjectType: DynamicObject
|
||||
|
||||
var from: From<ObjectType> { get set }
|
||||
var sectionBy: SectionBy<ObjectType> { get set }
|
||||
var fetchClauses: [FetchClause] { get set }
|
||||
}
|
||||
|
||||
|
||||
// MARK: - FetchChainBuilder
|
||||
|
||||
public struct FetchChainBuilder<D: DynamicObject>: FetchChainableBuilderType {
|
||||
|
||||
// MARK: FetchChainableBuilderType
|
||||
|
||||
public typealias ObjectType = D
|
||||
|
||||
public var from: From<D>
|
||||
public var fetchClauses: [FetchClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - QueryChainBuilder
|
||||
|
||||
public struct QueryChainBuilder<D: DynamicObject, R: SelectResultType>: QueryChainableBuilderType {
|
||||
|
||||
// MARK: QueryChainableBuilderType
|
||||
|
||||
public typealias ObjectType = D
|
||||
public typealias ResultType = R
|
||||
|
||||
public var from: From<D>
|
||||
public var select: Select<D, R>
|
||||
public var queryClauses: [QueryClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SectionMonitorChainBuilder
|
||||
|
||||
@available(OSX 10.12, *)
|
||||
public struct SectionMonitorChainBuilder<D: DynamicObject>: SectionMonitorBuilderType {
|
||||
|
||||
// MARK: SectionMonitorBuilderType
|
||||
|
||||
public var from: From<D>
|
||||
public var sectionBy: SectionBy<D>
|
||||
public var fetchClauses: [FetchClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - From
|
||||
|
||||
public extension From {
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` that starts with the specified `Where` clause
|
||||
|
||||
- parameter clause: the `Where` clause to create a `FetchChainBuilder` with
|
||||
- returns: a `FetchChainBuilder` that starts with the specified `Where` clause
|
||||
*/
|
||||
public func `where`(_ clause: Where<D>) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: clause)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` with a predicate using the specified string format and arguments
|
||||
|
||||
- parameter format: the format string for the predicate
|
||||
- parameter args: the arguments for `format`
|
||||
- returns: a `FetchChainBuilder` with a predicate using the specified string format and arguments
|
||||
*/
|
||||
public func `where`(format: String, _ args: Any...) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Where<D>(format, argumentArray: args))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` with a predicate using the specified string format and arguments
|
||||
|
||||
- parameter format: the format string for the predicate
|
||||
- parameter argumentArray: the arguments for `format`
|
||||
- returns: a `FetchChainBuilder` with a predicate using the specified string format and arguments
|
||||
*/
|
||||
public func `where`(format: String, argumentArray: [Any]?) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Where<D>(format, argumentArray: argumentArray))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` with a series of `SortKey`s
|
||||
|
||||
- parameter sortKey: a single `SortKey`
|
||||
- parameter sortKeys: a series of other `SortKey`s
|
||||
- returns: a `FetchChainBuilder` with a series of `SortKey`s
|
||||
*/
|
||||
public func orderBy(_ sortKey: OrderBy<D>.SortKey, _ sortKeys: OrderBy<D>.SortKey...) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: OrderBy<D>([sortKey] + sortKeys))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` with a closure where the `NSFetchRequest` may be configured
|
||||
|
||||
- parameter fetchRequest: the block to customize the `NSFetchRequest`
|
||||
- returns: a `FetchChainBuilder` with closure where the `NSFetchRequest` may be configured
|
||||
*/
|
||||
public func tweak(_ fetchRequest: @escaping (NSFetchRequest<NSFetchRequestResult>) -> Void) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Tweak(fetchRequest))
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` and immediately appending a `FetchClause`
|
||||
|
||||
- parameter clause: the `FetchClause` to add to the `FetchChainBuilder`
|
||||
- returns: a `FetchChainBuilder` containing the specified `FetchClause`
|
||||
*/
|
||||
public func appending(_ clause: FetchClause) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: clause)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `FetchChainBuilder` and immediately appending a series of `FetchClause`s
|
||||
|
||||
- parameter clauses: the `FetchClause`s to add to the `FetchChainBuilder`
|
||||
- returns: a `FetchChainBuilder` containing the specified `FetchClause`s
|
||||
*/
|
||||
public func appending<S: Sequence>(contentsOf clauses: S) -> FetchChainBuilder<D> where S.Element == FetchClause {
|
||||
|
||||
return self.fetchChain(appending: clauses)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `QueryChainBuilder` that starts with the specified `Select` clause
|
||||
|
||||
- parameter clause: the `Select` clause to create a `QueryChainBuilder` with
|
||||
- returns: a `QueryChainBuilder` that starts with the specified `Select` clause
|
||||
*/
|
||||
public func select<R>(_ clause: Select<D, R>) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return .init(
|
||||
@@ -115,11 +126,26 @@ public extension From {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `QueryChainBuilder` that starts with a `Select` clause created from the specified `SelectTerm`s
|
||||
|
||||
- parameter resultType: the generic `SelectResultType` for the `Select` clause
|
||||
- parameter selectTerm: a `SelectTerm`
|
||||
- parameter selectTerms: a series of `SelectTerm`s
|
||||
- returns: a `QueryChainBuilder` that starts with a `Select` clause created from the specified `SelectTerm`s
|
||||
*/
|
||||
public func select<R>(_ resultType: R.Type, _ selectTerm: SelectTerm<D>, _ selectTerms: SelectTerm<D>...) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.select(resultType, [selectTerm] + selectTerms)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `QueryChainBuilder` that starts with a `Select` clause created from the specified `SelectTerm`s
|
||||
|
||||
- parameter resultType: the generic `SelectResultType` for the `Select` clause
|
||||
- parameter selectTerms: a series of `SelectTerm`s
|
||||
- returns: a `QueryChainBuilder` that starts with a `Select` clause created from the specified `SelectTerm`s
|
||||
*/
|
||||
public func select<R>(_ resultType: R.Type, _ selectTerms: [SelectTerm<D>]) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return .init(
|
||||
@@ -129,6 +155,12 @@ public extension From {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `SectionMonitorChainBuilder` that starts with the `SectionBy` to use to group `ListMonitor` objects into sections
|
||||
|
||||
- parameter clause: the `SectionBy` to be used by the `ListMonitor`
|
||||
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public func sectionBy(_ clause: SectionBy<D>) -> SectionMonitorChainBuilder<D> {
|
||||
|
||||
@@ -139,12 +171,26 @@ public extension From {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
|
||||
|
||||
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public func sectionBy(_ sectionKeyPath: KeyPathString) -> SectionMonitorChainBuilder<D> {
|
||||
|
||||
return self.sectionBy(sectionKeyPath, { $0 })
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||
|
||||
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public func sectionBy(_ sectionKeyPath: KeyPathString, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> SectionMonitorChainBuilder<D> {
|
||||
|
||||
@@ -155,41 +201,6 @@ public extension From {
|
||||
)
|
||||
}
|
||||
|
||||
public func `where`(_ clause: Where<D>) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: clause)
|
||||
}
|
||||
|
||||
public func `where`(format: String, _ args: Any...) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Where<D>(format, argumentArray: args))
|
||||
}
|
||||
|
||||
public func `where`(format: String, argumentArray: [Any]?) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Where<D>(format, argumentArray: argumentArray))
|
||||
}
|
||||
|
||||
public func orderBy(_ sortKey: OrderBy<D>.SortKey, _ sortKeys: OrderBy<D>.SortKey...) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: OrderBy<D>([sortKey] + sortKeys))
|
||||
}
|
||||
|
||||
public func tweak(_ fetchRequest: @escaping (NSFetchRequest<NSFetchRequestResult>) -> Void) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: Tweak(fetchRequest))
|
||||
}
|
||||
|
||||
public func appending(_ clause: FetchClause) -> FetchChainBuilder<D> {
|
||||
|
||||
return self.fetchChain(appending: clause)
|
||||
}
|
||||
|
||||
public func appending<S: Sequence>(contentsOf clauses: S) -> FetchChainBuilder<D> where S.Element == FetchClause {
|
||||
|
||||
return self.fetchChain(appending: clauses)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@@ -367,21 +378,6 @@ public extension FetchChainBuilder where D: CoreStoreObject {
|
||||
|
||||
public extension QueryChainBuilder {
|
||||
|
||||
public func groupBy(_ clause: GroupBy<D>) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: clause)
|
||||
}
|
||||
|
||||
public func groupBy(_ keyPath: KeyPathString, _ keyPaths: KeyPathString...) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.groupBy(GroupBy<D>([keyPath] + keyPaths))
|
||||
}
|
||||
|
||||
public func groupBy(_ keyPaths: [KeyPathString]) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: GroupBy<D>(keyPaths))
|
||||
}
|
||||
|
||||
public func `where`(_ clause: Where<D>) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: clause)
|
||||
@@ -407,6 +403,21 @@ public extension QueryChainBuilder {
|
||||
return self.queryChain(appending: Tweak(fetchRequest))
|
||||
}
|
||||
|
||||
public func groupBy(_ clause: GroupBy<D>) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: clause)
|
||||
}
|
||||
|
||||
public func groupBy(_ keyPath: KeyPathString, _ keyPaths: KeyPathString...) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.groupBy(GroupBy<D>([keyPath] + keyPaths))
|
||||
}
|
||||
|
||||
public func groupBy(_ keyPaths: [KeyPathString]) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: GroupBy<D>(keyPaths))
|
||||
}
|
||||
|
||||
public func appending(_ clause: QueryClause) -> QueryChainBuilder<D, R> {
|
||||
|
||||
return self.queryChain(appending: clause)
|
||||
86
Sources/QueryChainBuilder.swift
Normal file
86
Sources/QueryChainBuilder.swift
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// QueryChainBuilder.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - QueryChainBuilder
|
||||
|
||||
/**
|
||||
The fetch builder type used for a queries. A `QueryChainBuilder` is created from a `From` clause and then a `select(...)` chain.
|
||||
```
|
||||
let averageAdultAge = dataStack.queryValue(
|
||||
From<MyPersonEntity>()
|
||||
.select(Int.self, .average(\.age))
|
||||
.where(\.age > 18)
|
||||
)
|
||||
```
|
||||
*/
|
||||
public struct QueryChainBuilder<D: DynamicObject, R: SelectResultType>: QueryChainableBuilderType {
|
||||
|
||||
// MARK: QueryChainableBuilderType
|
||||
|
||||
public typealias ObjectType = D
|
||||
public typealias ResultType = R
|
||||
|
||||
public var from: From<D>
|
||||
public var select: Select<D, R>
|
||||
public var queryClauses: [QueryClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - QueryChainableBuilderType
|
||||
|
||||
/**
|
||||
Utility protocol for `QueryChainBuilder`. Used in fetch methods that support chained query builders.
|
||||
*/
|
||||
public protocol QueryChainableBuilderType {
|
||||
|
||||
/**
|
||||
The `DynamicObject` type for the query
|
||||
*/
|
||||
associatedtype ObjectType: DynamicObject
|
||||
|
||||
/**
|
||||
The `SelectResultType` type for the query
|
||||
*/
|
||||
associatedtype ResultType: SelectResultType
|
||||
|
||||
/**
|
||||
The `From` clause specifies the source entity and source persistent store for the query
|
||||
*/
|
||||
var from: From<ObjectType> { get set }
|
||||
|
||||
/**
|
||||
The `Select` clause to be used for the query
|
||||
*/
|
||||
var select: Select<ObjectType, ResultType> { get set }
|
||||
|
||||
/**
|
||||
The `QueryClause`s to be used for the query
|
||||
*/
|
||||
var queryClauses: [QueryClause] { get set }
|
||||
}
|
||||
81
Sources/SectionMonitorBuilder.swift
Normal file
81
Sources/SectionMonitorBuilder.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// SectionMonitorBuilder.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
|
||||
// MARK: - SectionMonitorChainBuilder
|
||||
|
||||
/**
|
||||
The fetch builder type used for a sectioned `ListMonitor`. A `SectionMonitorChainBuilder` is created from a `From` clause and then a `sectionBy(...)` chain.
|
||||
```
|
||||
let monitor = transaction.monitorSectionedList(
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public struct SectionMonitorChainBuilder<D: DynamicObject>: SectionMonitorBuilderType {
|
||||
|
||||
// MARK: SectionMonitorBuilderType
|
||||
|
||||
public var from: From<D>
|
||||
public var sectionBy: SectionBy<D>
|
||||
public var fetchClauses: [FetchClause] = []
|
||||
}
|
||||
|
||||
|
||||
// MARK: - SectionMonitorBuilderType
|
||||
|
||||
/**
|
||||
Utility protocol for `SectionMonitorChainBuilder`. Used in methods that support chained fetch builders.
|
||||
*/
|
||||
@available(OSX 10.12, *)
|
||||
public protocol SectionMonitorBuilderType {
|
||||
|
||||
/**
|
||||
The `DynamicObject` type for the `ListMonitor`
|
||||
*/
|
||||
associatedtype ObjectType: DynamicObject
|
||||
|
||||
/**
|
||||
The `From` clause specifies the source entity and source persistent store for the `ListMonitor`
|
||||
*/
|
||||
var from: From<ObjectType> { get set }
|
||||
|
||||
/**
|
||||
The `SectionBy` clause to be used for the `ListMonitor`
|
||||
*/
|
||||
var sectionBy: SectionBy<ObjectType> { get set }
|
||||
|
||||
/**
|
||||
The `FetchClause`s to be used for the `ListMonitor`
|
||||
*/
|
||||
var fetchClauses: [FetchClause] { get set }
|
||||
}
|
||||
@@ -83,7 +83,23 @@ public extension UnsafeDataTransaction {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType` built from a chain of clauses. Since `NSFetchedResultsController` greedily locks the persistent store on initial fetch, you may prefer this method instead of the synchronous counterpart to avoid deadlocks while background updates/saves are being executed.
|
||||
|
||||
```
|
||||
transaction.monitorList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter createAsynchronously: the closure that receives the created `ListMonitor` instance
|
||||
- parameter clauseChain: a `FetchChainableBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `FetchChainableBuilderType`
|
||||
*/
|
||||
public func monitorList<B: FetchChainableBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorList(clauseChain.from, clauseChain.fetchClauses)
|
||||
@@ -176,7 +192,19 @@ public extension UnsafeDataTransaction {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
let monitor = transaction.monitorSectionedList(
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(_ clauseChain: B) -> ListMonitor<B.ObjectType> {
|
||||
|
||||
return self.monitorSectionedList(
|
||||
@@ -226,7 +254,22 @@ public extension UnsafeDataTransaction {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: docs
|
||||
/**
|
||||
Asynchronously creates a `ListMonitor` for a sectioned list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType` built from a chain of clauses.
|
||||
```
|
||||
transaction.monitorSectionedList(
|
||||
{ (monitor) in
|
||||
self.monitor = monitor
|
||||
},
|
||||
From<MyPersonEntity>()
|
||||
.sectionBy(\.age, { "\($0!) years old" })
|
||||
.where(\.age > 18)
|
||||
.orderBy(.ascending(\.age))
|
||||
)
|
||||
```
|
||||
- parameter clauseChain: a `SectionMonitorBuilderType` built from a chain of clauses
|
||||
- returns: a `ListMonitor` for a list of `DynamicObject`s that satisfy the specified `SectionMonitorBuilderType`
|
||||
*/
|
||||
public func monitorSectionedList<B: SectionMonitorBuilderType>(createAsynchronously: @escaping (ListMonitor<B.ObjectType>) -> Void, _ clauseChain: B) {
|
||||
|
||||
self.monitorSectionedList(
|
||||
|
||||
@@ -2,8 +2,25 @@
|
||||
// WhereClauseType.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Created by John Estropia on 2017/09/29.
|
||||
// Copyright © 2017 John Rommel Estropia. All rights reserved.
|
||||
// Copyright © 2017 John Rommel Estropia
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
Reference in New Issue
Block a user