This commit is contained in:
John Estropia
2020-08-17 17:09:41 +09:00
parent d988daa025
commit 72f36e7237
6 changed files with 259 additions and 5 deletions

View File

@@ -10,7 +10,7 @@ extension Modern.PokedexDemo {
// MARK: - Modern.PokedexDemo.Move
enum PokemonType: String, CaseIterable, FieldStorableType {
enum PokemonType: String, CaseIterable, ImportableAttributeType, FieldStorableType {
// MARK: Internal

View File

@@ -808,6 +808,39 @@ extension QueryChainBuilder where O: CoreStoreObject {
return self.queryChain(appending: clause(O.meta))
}
/**
Adds a `GroupBy` clause to the `QueryChainBuilder`
- parameter keyPath: a key path to group the query results with
- returns: a new `QueryChainBuilder` containing the `GroupBy` clause
*/
public func groupBy<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<T>>) -> QueryChainBuilder<O, R> {
return self.groupBy(GroupBy<O>(keyPath))
}
/**
Adds a `GroupBy` clause to the `QueryChainBuilder`
- parameter keyPath: a key path to group the query results with
- returns: a new `QueryChainBuilder` containing the `GroupBy` clause
*/
public func groupBy<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>) -> QueryChainBuilder<O, R> {
return self.groupBy(GroupBy<O>(keyPath))
}
/**
Adds a `GroupBy` clause to the `QueryChainBuilder`
- parameter keyPath: a key path to group the query results with
- returns: a new `QueryChainBuilder` containing the `GroupBy` clause
*/
public func groupBy<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Coded<T>>) -> QueryChainBuilder<O, R> {
return self.groupBy(GroupBy<O>(keyPath))
}
/**
Adds a `GroupBy` clause to the `QueryChainBuilder`

View File

@@ -124,6 +124,36 @@ extension GroupBy where O: NSManagedObject {
extension GroupBy where O: CoreStoreObject {
/**
Initializes a `GroupBy` clause with a key path
- parameter keyPath: a key path to group results with
*/
public init<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Stored<T>>) {
self.init([O.meta[keyPath: keyPath].keyPath])
}
/**
Initializes a `GroupBy` clause with a key path
- parameter keyPath: a key path to group results with
*/
public init<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>) {
self.init([O.meta[keyPath: keyPath].keyPath])
}
/**
Initializes a `GroupBy` clause with a key path
- parameter keyPath: a key path to group results with
*/
public init<T>(_ keyPath: KeyPath<O, FieldContainer<O>.Coded<T>>) {
self.init([O.meta[keyPath: keyPath].keyPath])
}
/**
Initializes a `GroupBy` clause with a key path

View File

@@ -419,6 +419,94 @@ import Combine
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
extension ListPublisher: ObservableObject {}
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
extension ListPublisher: Publisher {
// MARK: Publisher
public typealias Output = ListSnapshot<O>
public typealias Failure = Never
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
subscriber.receive(
subscription: ListSnapshotSubscription(
publisher: self,
subscriber: subscriber
)
)
}
// MARK: - ListSnapshotSubscriber
fileprivate final class ListSnapshotSubscriber: Subscriber {
// MARK: Subscriber
typealias Failure = Never
func receive(subscription: Subscription) {
subscription.request(.unlimited)
}
func receive(_ input: Output) -> Subscribers.Demand {
return .unlimited
}
func receive(completion: Subscribers.Completion<Failure>) {}
}
// MARK: - ListSnapshotSubscription
fileprivate final class ListSnapshotSubscription<S: Subscriber>: Subscription where S.Input == Output, S.Failure == Never {
// MARK: FilePrivate
init(publisher: ListPublisher<O>, subscriber: S) {
self.publisher = publisher
self.subscriber = subscriber
}
// MARK: Subscription
func request(_ demand: Subscribers.Demand) {
guard demand > 0 else {
return
}
self.publisher.addObserver(self) { [weak self] (publisher) in
guard let self = self, let subscriber = self.subscriber else {
return
}
_ = subscriber.receive(publisher.snapshot)
}
}
// MARK: Cancellable
func cancel() {
self.publisher.removeObserver(self)
self.subscriber = nil
}
// MARK: Private
private let publisher: ListPublisher<O>
private var subscriber: S?
}
}
#endif
// MARK: - ListPublisher

View File

@@ -79,7 +79,7 @@ public struct ObjectProxy<O: CoreStoreObject> {
/**
Returns the value for the specified property from the objects private internal storage.
Accessing this property does not invoke the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`). This method is used primarily to implement custom accessor methods that need direct access to the object's private storage.
This method is used primarily to implement custom accessor methods that need direct access to the object's private storage.
*/
public var primitiveValue: V? {
@@ -95,8 +95,6 @@ public struct ObjectProxy<O: CoreStoreObject> {
/**
Returns the value for the property identified by a given key.
Accessing this property triggers the access notification methods (`willAccessValue(forKey:)` and `didAccessValue(forKey:)`).
*/
public var value: V {
@@ -147,6 +145,11 @@ public struct ObjectProxy<O: CoreStoreObject> {
}
self.setPrimitiveValue = {
rawObject.willChangeValue(forKey: keyPathString)
defer {
rawObject.didChangeValue(forKey: keyPathString)
}
rawObject.setPrimitiveValue(
$0.cs_toFieldStoredNativeType(),
forKey: keyPathString
@@ -179,7 +182,7 @@ public struct ObjectProxy<O: CoreStoreObject> {
}
}
self.setPrimitiveValue = {
rawObject.setPrimitiveValue(
$0,
forKey: keyPathString
@@ -216,7 +219,12 @@ public struct ObjectProxy<O: CoreStoreObject> {
}
}
self.setPrimitiveValue = {
rawObject.willChangeValue(forKey: keyPathString)
defer {
rawObject.didChangeValue(forKey: keyPathString)
}
rawObject.setPrimitiveValue(
$0,
forKey: keyPathString

View File

@@ -288,6 +288,101 @@ import Combine
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
extension ObjectPublisher: ObservableObject {}
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
extension ObjectPublisher: Publisher {
// MARK: Publisher
public typealias Output = ObjectSnapshot<O>
public typealias Failure = Never
public func receive<S: Subscriber>(subscriber: S) where S.Input == Output, S.Failure == Failure {
subscriber.receive(
subscription: ObjectSnapshotSubscription(
publisher: self,
subscriber: subscriber
)
)
}
// MARK: - ObjectSnapshotSubscriber
fileprivate final class ObjectSnapshotSubscriber: Subscriber {
// MARK: Subscriber
typealias Failure = Never
func receive(subscription: Subscription) {
subscription.request(.unlimited)
}
func receive(_ input: Output) -> Subscribers.Demand {
return .unlimited
}
func receive(completion: Subscribers.Completion<Failure>) {}
}
// MARK: - ObjectSnapshotSubscription
fileprivate final class ObjectSnapshotSubscription<S: Subscriber>: Subscription where S.Input == Output, S.Failure == Never {
// MARK: FilePrivate
init(publisher: ObjectPublisher<O>, subscriber: S) {
self.publisher = publisher
self.subscriber = subscriber
}
// MARK: Subscription
func request(_ demand: Subscribers.Demand) {
guard demand > 0 else {
return
}
self.publisher.addObserver(self) { [weak self] (publisher) in
guard let self = self, let subscriber = self.subscriber else {
return
}
if let snapshot = publisher.snapshot {
_ = subscriber.receive(snapshot)
}
else {
subscriber.receive(completion: .finished)
}
}
}
// MARK: Cancellable
func cancel() {
self.publisher.removeObserver(self)
self.subscriber = nil
}
// MARK: Private
private let publisher: ObjectPublisher<O>
private var subscriber: S?
}
}
#endif
// MARK: - ObjectPublisher