keyPath utilities for SectionBy clauses

This commit is contained in:
John Rommel Estropia
2017-09-24 10:38:17 +09:00
parent e814733ae9
commit 645034dde5
12 changed files with 207 additions and 58 deletions

View File

@@ -237,7 +237,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
return Static.timeZonesStack.queryValue( return Static.timeZonesStack.queryValue(
From<TimeZone>() From<TimeZone>()
.select(NSNumber.self, .count(#keyPath(TimeZone.name))) .select(NSNumber.self, .count(\.name))
)! as Any )! as Any
} }
), ),
@@ -247,7 +247,7 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
return Static.timeZonesStack.queryValue( return Static.timeZonesStack.queryValue(
From<TimeZone>() From<TimeZone>()
.select(String.self, .attribute(#keyPath(TimeZone.abbreviation))) .select(String.self, .attribute(\.abbreviation))
.where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo") .where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)! as Any )! as Any
} }
@@ -260,10 +260,10 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
From<TimeZone>() From<TimeZone>()
.select( .select(
NSDictionary.self, NSDictionary.self,
.attribute(#keyPath(TimeZone.name)), .attribute(\.name),
.attribute(#keyPath(TimeZone.abbreviation)) .attribute(\.abbreviation)
) )
.orderBy(.ascending(#keyPath(TimeZone.name))) .orderBy(.ascending(\.name))
)! )!
} }
), ),
@@ -275,14 +275,14 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
From<TimeZone>() From<TimeZone>()
.select( .select(
NSDictionary.self, NSDictionary.self,
.count(#keyPath(TimeZone.abbreviation)), .count(\.abbreviation),
.attribute(#keyPath(TimeZone.abbreviation)) .attribute(\.abbreviation)
) )
.groupBy(#keyPath(TimeZone.abbreviation)) .groupBy(\.abbreviation)
.orderBy( .orderBy(
.ascending(#keyPath(TimeZone.secondsFromGMT)), .ascending(\.secondsFromGMT),
.ascending(#keyPath(TimeZone.name)) .ascending(\.name)
) )
)! )!
} }
), ),
@@ -291,13 +291,17 @@ class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSo
query: { () -> Any in query: { () -> Any in
return Static.timeZonesStack.queryAttributes( return Static.timeZonesStack.queryAttributes(
From<TimeZone>(), From<TimeZone>()
Select<NSDictionary>( .select(
.count(#keyPath(TimeZone.hasDaylightSavingTime), as: "numberOfCountries"), NSDictionary.self,
#keyPath(TimeZone.hasDaylightSavingTime) .count(\.hasDaylightSavingTime, as: "numberOfCountries"),
), .attribute(\.hasDaylightSavingTime)
GroupBy<TimeZone>(#keyPath(TimeZone.hasDaylightSavingTime)), )
OrderBy<TimeZone>(.descending(#keyPath(TimeZone.hasDaylightSavingTime))) .groupBy(\.hasDaylightSavingTime)
.orderBy(
.descending(\.hasDaylightSavingTime),
.ascending(\.name)
)
)! )!
} }
) )

View File

@@ -287,8 +287,8 @@ class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewD
self.set(dataStack: dataStack, model: model, scrollToSelection: true) self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = dataStack.queryValue( let count = dataStack.queryValue(
From(model.entityType), From<NSManagedObject>(model.entityType)
Select<Int>(.count(#keyPath(OrganismV1.dna))))! .select(Int.self, .count(#keyPath(OrganismV1.dna))))!
if count > 0 { if count > 0 {
self.setEnabled(true) self.setEnabled(true)

View File

@@ -39,13 +39,13 @@ final class SectionByTests: XCTestCase {
do { do {
let sectionBy = SectionBy("key") let sectionBy = SectionBy<NSManagedObject>("key")
XCTAssertEqual(sectionBy.sectionKeyPath, "key") XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key") XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
} }
do { do {
let sectionBy = SectionBy("key") { $0.flatMap { "\($0):suffix" } } let sectionBy = SectionBy<NSManagedObject>("key") { $0.flatMap { "\($0):suffix" } }
XCTAssertEqual(sectionBy.sectionKeyPath, "key") XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix") XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(nil)) XCTAssertNil(sectionBy.sectionIndexTransformer(nil))

View File

@@ -36,7 +36,7 @@ import CoreData
*/ */
@available(OSX 10.12, *) @available(OSX 10.12, *)
@objc @objc
public final class CSSectionBy: NSObject, CoreStoreObjectiveCType { public final class CSSectionBy: NSObject {
/** /**
Initializes a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections Initializes a `CSSectionBy` clause with the key path to use to group `CSListMonitor` objects into sections
@@ -47,7 +47,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
@objc @objc
public static func keyPath(_ sectionKeyPath: KeyPathString) -> CSSectionBy { public static func keyPath(_ sectionKeyPath: KeyPathString) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath)) return self.init(SectionBy<NSManagedObject>(sectionKeyPath))
} }
/** /**
@@ -60,7 +60,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
@objc @objc
public static func keyPath(_ sectionKeyPath: KeyPathString, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy { public static func keyPath(_ sectionKeyPath: KeyPathString, sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> CSSectionBy {
return self.init(SectionBy(sectionKeyPath, sectionIndexTransformer)) return self.init(SectionBy<NSManagedObject>(sectionKeyPath, sectionIndexTransformer))
} }
@@ -74,11 +74,11 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
// MARK: CoreStoreObjectiveCType // MARK: CoreStoreObjectiveCType
public let bridgeToSwift: SectionBy public let bridgeToSwift: SectionBy<NSManagedObject>
public init(_ swiftValue: SectionBy) { public init<D>(_ swiftValue: SectionBy<D>) {
self.bridgeToSwift = swiftValue self.bridgeToSwift = swiftValue.downcast()
super.init() super.init()
} }
} }
@@ -87,7 +87,7 @@ public final class CSSectionBy: NSObject, CoreStoreObjectiveCType {
// MARK: - SectionBy // MARK: - SectionBy
@available(OSX 10.12, *) @available(OSX 10.12, *)
extension SectionBy: CoreStoreSwiftType { extension SectionBy {
// MARK: CoreStoreSwiftType // MARK: CoreStoreSwiftType
@@ -95,4 +95,12 @@ extension SectionBy: CoreStoreSwiftType {
return CSSectionBy(self) return CSSectionBy(self)
} }
// MARK: FilePrivate
fileprivate func downcast() -> SectionBy<NSManagedObject> {
return SectionBy<NSManagedObject>(self.sectionKeyPath, self.sectionIndexTransformer)
}
} }

View File

@@ -51,7 +51,7 @@ public protocol SectionMonitorBuilderType {
associatedtype ObjectType: DynamicObject associatedtype ObjectType: DynamicObject
var from: From<ObjectType> { get set } var from: From<ObjectType> { get set }
var sectionBy: SectionBy { get set } var sectionBy: SectionBy<ObjectType> { get set }
var fetchClauses: [FetchClause] { get set } var fetchClauses: [FetchClause] { get set }
} }
@@ -92,7 +92,7 @@ public struct SectionMonitorChainBuilder<D: DynamicObject>: SectionMonitorBuilde
// MARK: SectionMonitorBuilderType // MARK: SectionMonitorBuilderType
public var from: From<D> public var from: From<D>
public var sectionBy: SectionBy public var sectionBy: SectionBy<D>
public var fetchClauses: [FetchClause] = [] public var fetchClauses: [FetchClause] = []
} }
@@ -101,6 +101,15 @@ public struct SectionMonitorChainBuilder<D: DynamicObject>: SectionMonitorBuilde
public extension From { public extension From {
public func select<R>(_ clause: Select<D, R>) -> QueryChainBuilder<D, R> {
return .init(
from: self,
select: clause,
queryClauses: []
)
}
public func select<R>(_ resultType: R.Type, _ selectTerm: SelectTerm<D>, _ selectTerms: SelectTerm<D>...) -> QueryChainBuilder<D, R> { public func select<R>(_ resultType: R.Type, _ selectTerm: SelectTerm<D>, _ selectTerms: SelectTerm<D>...) -> QueryChainBuilder<D, R> {
return self.select(resultType, [selectTerm] + selectTerms) return self.select(resultType, [selectTerm] + selectTerms)
@@ -115,6 +124,16 @@ public extension From {
) )
} }
@available(OSX 10.12, *)
public func sectionBy(_ clause: SectionBy<D>) -> SectionMonitorChainBuilder<D> {
return .init(
from: self,
sectionBy: clause,
fetchClauses: []
)
}
@available(OSX 10.12, *) @available(OSX 10.12, *)
public func sectionBy(_ sectionKeyPath: KeyPathString) -> SectionMonitorChainBuilder<D> { public func sectionBy(_ sectionKeyPath: KeyPathString) -> SectionMonitorChainBuilder<D> {

View File

@@ -115,7 +115,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<D> { public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses) return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
} }
@@ -128,7 +128,7 @@ public extension CoreStore {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<D> { public static func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses) return self.defaultStack.monitorSectionedList(from, sectionBy, fetchClauses)
} }
@@ -151,7 +151,7 @@ public extension CoreStore {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
} }
@@ -164,7 +164,7 @@ public extension CoreStore {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { public static func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) self.defaultStack.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
} }

View File

@@ -35,7 +35,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
// MARK: Internal // MARK: Internal
@nonobjc @nonobjc
internal convenience init<D>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) { internal convenience init<D>(dataStack: DataStack, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy<D>? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
self.init( self.init(
context: dataStack.mainContext, context: dataStack.mainContext,
@@ -47,7 +47,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
} }
@nonobjc @nonobjc
internal init<D>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) { internal init<D>(context: NSManagedObjectContext, fetchRequest: NSFetchRequest<NSManagedObject>, from: From<D>, sectionBy: SectionBy<D>? = nil, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
_ = from.applyToFetchRequest( _ = from.applyToFetchRequest(
fetchRequest, fetchRequest,

View File

@@ -154,7 +154,7 @@ public extension DataStack {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<D> { public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.monitorSectionedList(from, sectionBy, fetchClauses) return self.monitorSectionedList(from, sectionBy, fetchClauses)
} }
@@ -167,7 +167,7 @@ public extension DataStack {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<D> { public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
CoreStore.assert( CoreStore.assert(
Thread.isMainThread, Thread.isMainThread,
@@ -208,7 +208,7 @@ public extension DataStack {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
} }
@@ -221,7 +221,7 @@ public extension DataStack {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
CoreStore.assert( CoreStore.assert(
Thread.isMainThread, Thread.isMainThread,

View File

@@ -626,7 +626,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
// MARK: Internal // MARK: Internal
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) { internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
self.init( self.init(
context: dataStack.mainContext, context: dataStack.mainContext,
@@ -638,7 +638,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
) )
} }
internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) { internal convenience init(dataStack: DataStack, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) {
self.init( self.init(
context: dataStack.mainContext, context: dataStack.mainContext,
@@ -650,7 +650,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
) )
} }
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) { internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) {
self.init( self.init(
context: unsafeTransaction.context, context: unsafeTransaction.context,
@@ -662,7 +662,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
) )
} }
internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) { internal convenience init(unsafeTransaction: UnsafeDataTransaction, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: @escaping (ListMonitor<ObjectType>) -> Void) {
self.init( self.init(
context: unsafeTransaction.context, context: unsafeTransaction.context,
@@ -1041,7 +1041,7 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
} }
} }
private static func recreateFetchedResultsController(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) -> (controller: CoreStoreFetchedResultsController, delegate: FetchedResultsControllerDelegate) { private static func recreateFetchedResultsController(context: NSManagedObjectContext, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void) -> (controller: CoreStoreFetchedResultsController, delegate: FetchedResultsControllerDelegate) {
let fetchRequest = CoreStoreFetchRequest() let fetchRequest = CoreStoreFetchRequest()
fetchRequest.fetchLimit = 0 fetchRequest.fetchLimit = 0
@@ -1065,9 +1065,9 @@ public final class ListMonitor<D: DynamicObject>: Hashable {
} }
private let from: From<ObjectType> private let from: From<ObjectType>
private let sectionBy: SectionBy? private let sectionBy: SectionBy<ObjectType>?
private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<ObjectType>, sectionBy: SectionBy?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<ObjectType>) -> Void)?) { private init(context: NSManagedObjectContext, transactionQueue: DispatchQueue, from: From<ObjectType>, sectionBy: SectionBy<ObjectType>?, applyFetchClauses: @escaping (_ fetchRequest: NSFetchRequest<NSManagedObject>) -> Void, createAsynchronously: ((ListMonitor<ObjectType>) -> Void)?) {
self.isSectioned = (sectionBy != nil) self.isSectioned = (sectionBy != nil)
self.from = from self.from = from

View File

@@ -42,7 +42,7 @@ public extension DataStack {
- returns: an `NSFetchedResultsController` that observes the `DataStack` - returns: an `NSFetchedResultsController` that observes the `DataStack`
*/ */
@nonobjc @nonobjc
public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<D> { public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<D> {
return createFRC( return createFRC(
fromContext: self.mainContext, fromContext: self.mainContext,
@@ -62,7 +62,7 @@ public extension DataStack {
- returns: an `NSFetchedResultsController` that observes the `DataStack` - returns: an `NSFetchedResultsController` that observes the `DataStack`
*/ */
@nonobjc @nonobjc
public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> { public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> {
return createFRC( return createFRC(
fromContext: self.mainContext, fromContext: self.mainContext,
@@ -127,7 +127,7 @@ public extension UnsafeDataTransaction {
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction` - returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
*/ */
@nonobjc @nonobjc
public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<D> { public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> NSFetchedResultsController<D> {
return createFRC( return createFRC(
fromContext: self.context, fromContext: self.context,
@@ -147,7 +147,7 @@ public extension UnsafeDataTransaction {
- returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction` - returns: an `NSFetchedResultsController` that observes the `UnsafeDataTransaction`
*/ */
@nonobjc @nonobjc
public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> { public func createFetchedResultsController<D: NSManagedObject>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> {
return createFRC( return createFRC(
fromContext: self.context, fromContext: self.context,
@@ -201,7 +201,7 @@ public extension UnsafeDataTransaction {
// MARK: - Private // MARK: - Private
@available(OSX 10.12, *) @available(OSX 10.12, *)
fileprivate func createFRC<D: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<D>, sectionBy: SectionBy? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> { fileprivate func createFRC<D: NSManagedObject>(fromContext context: NSManagedObjectContext, from: From<D>, sectionBy: SectionBy<D>? = nil, fetchClauses: [FetchClause]) -> NSFetchedResultsController<D> {
let controller = CoreStoreFetchedResultsController( let controller = CoreStoreFetchedResultsController(
context: context, context: context,

View File

@@ -40,7 +40,7 @@ import CoreData
``` ```
*/ */
@available(OSX 10.12, *) @available(OSX 10.12, *)
public struct SectionBy { public struct SectionBy<D: DynamicObject> {
/** /**
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
@@ -71,3 +71,121 @@ public struct SectionBy {
internal let sectionKeyPath: KeyPathString internal let sectionKeyPath: KeyPathString
internal let sectionIndexTransformer: (_ sectionName: String?) -> String? internal let sectionIndexTransformer: (_ sectionName: String?) -> String?
} }
@available(OSX 10.12, *)
public extension SectionBy where D: NSManagedObject {
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, T>) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, T>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
self.init(sectionKeyPath._kvcKeyPathString!, sectionIndexTransformer)
}
}
@available(OSX 10.12, *)
public extension SectionBy where D: CoreStoreObject {
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, ValueContainer<D>.Required<T>>) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, ValueContainer<D>.Optional<T>>) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, TransformableContainer<D>.Required<T>>) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, TransformableContainer<D>.Optional<T>>) {
self.init(sectionKeyPath, { $0 })
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, ValueContainer<D>.Required<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
self.init(D.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, ValueContainer<D>.Optional<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
self.init(D.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, TransformableContainer<D>.Required<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
self.init(D.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
}
/**
Initializes a `SectionBy` clause 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
*/
public init<T>(_ sectionKeyPath: KeyPath<D, TransformableContainer<D>.Optional<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
self.init(D.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
}
}

View File

@@ -145,7 +145,7 @@ public extension UnsafeDataTransaction {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) -> ListMonitor<D> { public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) -> ListMonitor<D> {
return self.monitorSectionedList(from, sectionBy, fetchClauses) return self.monitorSectionedList(from, sectionBy, fetchClauses)
} }
@@ -158,7 +158,7 @@ public extension UnsafeDataTransaction {
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
- returns: a `ListMonitor` instance that monitors changes to the list - returns: a `ListMonitor` instance that monitors changes to the list
*/ */
public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) -> ListMonitor<D> { public func monitorSectionedList<D>(_ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) -> ListMonitor<D> {
CoreStore.assert( CoreStore.assert(
fetchClauses.filter { $0 is OrderBy<D> }.count > 0, fetchClauses.filter { $0 is OrderBy<D> }.count > 0,
@@ -194,7 +194,7 @@ public extension UnsafeDataTransaction {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: FetchClause...) { public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: FetchClause...) {
self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses) self.monitorSectionedList(createAsynchronously: createAsynchronously, from, sectionBy, fetchClauses)
} }
@@ -207,7 +207,7 @@ public extension UnsafeDataTransaction {
- parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections. - parameter sectionBy: a `SectionBy` clause indicating the keyPath for the attribute to use when sorting the list into sections.
- parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses. - parameter fetchClauses: a series of `FetchClause` instances for fetching the object list. Accepts `Where`, `OrderBy`, and `Tweak` clauses.
*/ */
public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy, _ fetchClauses: [FetchClause]) { public func monitorSectionedList<D>(createAsynchronously: @escaping (ListMonitor<D>) -> Void, _ from: From<D>, _ sectionBy: SectionBy<D>, _ fetchClauses: [FetchClause]) {
CoreStore.assert( CoreStore.assert(
fetchClauses.filter { $0 is OrderBy<D> }.count > 0, fetchClauses.filter { $0 is OrderBy<D> }.count > 0,