Removed ObservableObject implementations of ListPublisher/ObjectPublisher in favor of LiveList/LiveObject and ".reactive" publishers

This commit is contained in:
John Estropia
2021-03-07 10:38:53 +09:00
parent 098e560fcc
commit 0b127956d3
5 changed files with 38 additions and 376 deletions

View File

@@ -25,16 +25,6 @@
import CoreData
#if canImport(Combine)
import Combine
#endif
#if canImport(SwiftUI)
import SwiftUI
#endif
// MARK: - ListPublisher
@@ -89,13 +79,8 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
*/
public fileprivate(set) var snapshot: ListSnapshot<O> = .init() {
willSet {
self.willChange()
}
didSet {
self.didChange()
self.notifyObservers()
}
}
@@ -315,11 +300,6 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
self.fetchedResultsControllerDelegate.fetchedResultsController = nil
self.observers.removeAllObjects()
}
// MARK: FilePrivate
fileprivate let rawObjectWillChange: Any?
// MARK: Private
@@ -375,21 +355,6 @@ public final class ListPublisher<O: DynamicObject>: Hashable {
applyFetchClauses: applyFetchClauses
)
if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
#if canImport(Combine)
self.rawObjectWillChange = ObservableObjectPublisher()
#else
self.rawObjectWillChange = nil
#endif
}
else {
self.rawObjectWillChange = nil
}
self.fetchedResultsControllerDelegate.handler = self
try! self.fetchedResultsController.performFetchFromSpecifiedStores()
@@ -428,143 +393,3 @@ extension ListPublisher: FetchedDiffableDataSourceSnapshotHandler {
)
}
}
#if canImport(Combine)
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
extension ListPublisher {
// MARK: ObservableObject
#if canImport(Combine)
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
public var objectWillChange: ObservableObjectPublisher {
return self.rawObjectWillChange! as! ObservableObjectPublisher
}
#endif
fileprivate func willChange() {
guard #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) else {
return
}
#if canImport(Combine)
#if canImport(SwiftUI)
withAnimation {
self.objectWillChange.send()
}
#endif
self.objectWillChange.send()
#endif
}
fileprivate func didChange() {
// nothing
}
}

View File

@@ -76,6 +76,11 @@ public struct LiveObject<O: DynamicObject>: DynamicProperty {
return self.observer.item
}
public var projectedValue: ObjectPublisher<O>? {
return self.observer.objectPublisher
}
// MARK: DynamicProperty

View File

@@ -25,16 +25,6 @@
import CoreData
#if canImport(Combine)
import Combine
#endif
#if canImport(SwiftUI)
import SwiftUI
#endif
// MARK: - ObjectPublisher
@@ -226,26 +216,10 @@ public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hash
// MARK: FilePrivate
fileprivate let rawObjectWillChange: Any?
fileprivate init(objectID: O.ObjectID, context: NSManagedObjectContext, initializer: @escaping (NSManagedObjectID, NSManagedObjectContext) -> ObjectSnapshot<O>?) {
self.id = objectID
self.context = context
if #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) {
#if canImport(Combine)
self.rawObjectWillChange = ObservableObjectPublisher()
#else
self.rawObjectWillChange = nil
#endif
}
else {
self.rawObjectWillChange = nil
}
self.$lazySnapshot.initialize { [weak self] in
guard let self = self else {
@@ -262,16 +236,12 @@ public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hash
self.object = nil
self.willChange()
self.$lazySnapshot.reset({ nil })
self.didChange()
self.notifyObservers()
}
else if updatedIDs.contains(objectID) {
self.willChange()
self.$lazySnapshot.reset({ initializer(objectID, context) })
self.didChange()
self.notifyObservers()
}
}
@@ -305,154 +275,6 @@ public final class ObjectPublisher<O: DynamicObject>: ObjectRepresentation, Hash
}
#if canImport(Combine)
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
extension ObjectPublisher {
// MARK: ObservableObject
#if canImport(Combine)
@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *)
public var objectWillChange: ObservableObjectPublisher {
return self.rawObjectWillChange! as! ObservableObjectPublisher
}
#endif
fileprivate func willChange() {
guard #available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) else {
return
}
#if canImport(Combine)
#if canImport(SwiftUI)
withAnimation {
self.objectWillChange.send()
}
#endif
self.objectWillChange.send()
#endif
}
fileprivate func didChange() {
// nothing
}
}
// MARK: - ObjectPublisher where O: NSManagedObject
extension ObjectPublisher where O: NSManagedObject {