Skip to content

Instantly share code, notes, and snippets.

@swhitty
Last active July 29, 2022 06:57
Show Gist options
  • Save swhitty/4221d1993dd9563c9464de50bcba9cf1 to your computer and use it in GitHub Desktop.
Save swhitty/4221d1993dd9563c9464de50bcba9cf1 to your computer and use it in GitHub Desktop.
import Combine
import Foundation
func copyValues<T>(at keyPaths: [PartialKeyPath<T>], from source: T, to destination: inout T) {
for keyPath in keyPaths.compactMap({ $0 as? any ValueCopyingKeyPath }) {
keyPath.copyValue(from: source, to: &destination)
}
}
extension _KeyValueCodingAndObservingPublishing where Self: NSObject {
func publisher(forAll keyPaths: [PartialKeyPath<Self>], options: NSKeyValueObservingOptions = [.new]) -> AnyPublisher<Void, Never> {
let publishers = keyPaths.compactMap { ($0 as? any PublishableKeyPath)?.publisher(on: self, options: options) }
return Publishers.MergeMany(publishers)
.eraseToAnyPublisher()
}
}
extension KeyPath: PublishableKeyPath where Root: NSObject {
func publisher<T: NSObject>(on object: T, options: NSKeyValueObservingOptions) -> AnyPublisher<Void, Never>? {
precondition(object is Root)
return unsafeDowncast(object, to: Root.self)
.publisher(for: self, options: options)
.map { _ in () }
.eraseToAnyPublisher()
}
}
extension WritableKeyPath: ValueCopyingKeyPath {
func copyValue<T>(from source: T, to destination: inout T) {
precondition(source is Root)
precondition(destination is Root)
let keyPath = unsafeDowncast(self, to: WritableKeyPath<T, Value>.self)
destination[keyPath: keyPath] = source[keyPath: keyPath]
}
}
private protocol PublishableKeyPath {
associatedtype Root
func publisher<T: NSObject>(on object: T, options: NSKeyValueObservingOptions) -> AnyPublisher<Void, Never>?
}
private protocol ValueCopyingKeyPath {
associatedtype Root
func copyValue<T>(from source: T, to destination: inout T)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment