SwiftyUserDefaults
SwiftyUserDefaults copied to clipboard
Have you ever thought of making some adjustments to RxSwift?
Have you ever thought of making some adjustments to RxSwift?
Like the following?
import RxCocoa
import RxSwift
/// Maintain life cycle UnsafeRawPointer
private var keeplive = "defaultkeeplive"
extension DefaultsKey{
private var keepLiveObservalue:NSObject?{
set(newvalue){ objc_setAssociatedObject(self, &keeplive, newvalue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } // Save keep live obj
get{ return nil } // In order to save trouble...
}
/// Make a Binder according to the DefaultsKey provided.
/// Binder Value Type == DefailtsKey ValueType
var binder:Binder<ValueType>{
let keepliveobj = NSObject()
self.keepLiveObservalue = keepliveobj
return Binder(keepliveobj) { _, value in
Defaults[self] = value
}
}
/// Make a Observable according to the DefaultsKey provided.
/// Observable Element Type == DefailtsKey ValueType
var observable:Observable<ValueType>{
return UserDefaults.standard.rx.observe(ValueType.self, self._key)
.filter{ $0 != nil }.map{ $0! } // If you use RxOptional, it will be better.
}
}
Rx is fun! I think it would be inappropriate to have this as part of SwiftyUserDefaults, because there shouldn't be a forced dependency on RxSwift, but as an extension library — yeah!
Extending on that, I'm facing issues because I'm using ReactiveSwift and its reactive extension won't use the default value provided on DefaultsKey initialiser. I'm happy to adapt my code but would be convenient if internal let defaultValue: ValueType? property would be public instead of internal.
I think making defaultValue public and read-only will be useful, too!
Also @0x30 what about an Rx extension in https://github.com/RxSwiftCommunity/ ?
Ok, I may not express it very clearly, I hope I can get a configuration similar to Moya.
s.subspec "ReactiveSwift" do |ss|
ss.source_files = "Sources/ReactiveMoya/"
ss.dependency "Moya/Core"
ss.dependency "ReactiveSwift", "~> 5.0"
end
s.subspec "RxSwift" do |ss|
ss.source_files = "Sources/RxMoya/"
ss.dependency "Moya/Core"
ss.dependency "RxSwift", "~> 4.0"
end
Aha! Well, this would require the SwiftyUserDefaults maintainers to care for the reactive extensions, which is now only 2 people it seems. If they don't want to, and someone else starts with a RxSwiftCommunity repo, the extension can be maintained by a larger group of Rx fans, which makes the extension more resilient in the long term. (But will require you to import RxSwiftyUserDefaults on top of this library.)
This is how I started in my app during the v4.0 transition, btw:
extension Reactive where Base: UserDefaults {
func observe<T: DefaultsSerializable>(key: DefaultsKey<T>, options: NSKeyValueObservingOptions = [.old, .new]) -> RxSwift.Observable<T.T?> {
return Observable.create { observer -> Disposable in
let token = self.base.observe(key: key, options: options) { update in
observer.onNext(update.newValue)
}
return Disposables.create {
token.dispose()
}
}
}
}
This is how I started in my app during the v4.0 transition
is there an updated sample for v5?
Edit: got it to work properly:
extension DefaultsAdapter {
func observe<T: DefaultsSerializable>(_ key: DefaultsKey<T>,
options: NSKeyValueObservingOptions = [.old, .new]
) -> RxSwift.Observable<DefaultsObserver<T>.Update> where T == T.T {
Observable.create { observer in
let token = self.observe(key, options: options) { update in
observer.onNext(update)
}
return Disposables.create {
token.dispose()
}
}
}
func observe<T: DefaultsSerializable>(_ keyPath: KeyPath<KeyStore, DefaultsKey<T>>,
options: NSKeyValueObservingOptions = [.old, .new]
) -> RxSwift.Observable<DefaultsObserver<T>.Update> where T == T.T {
Observable.create { observer in
let token = self.observe(keyPath, options: options) { update in
observer.onNext(update)
}
return Disposables.create {
token.dispose()
}
}
}
}