Skip to content

Commit

Permalink
Hides accidentally exposed NSKeyValueObservingOptions. ReactiveX#1164
Browse files Browse the repository at this point in the history
  • Loading branch information
kzaher committed Jun 19, 2017
1 parent 142184b commit 43cf3b1
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 15 deletions.
4 changes: 2 additions & 2 deletions Documentation/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -941,13 +941,13 @@ There are two built in ways this library supports KVO.
```swift
// KVO
extension Reactive where Base: NSObject {
public func observe<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions, retainSelf: Bool = true) -> Observable<E?> {}
public func observe<E>(type: E.Type, _ keyPath: String, options: KeyValueObservingOptions, retainSelf: Bool = true) -> Observable<E?> {}
}

#if !DISABLE_SWIZZLING
// KVO
extension Reactive where Base: NSObject {
public func observeWeakly<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions) -> Observable<E?> {}
public func observeWeakly<E>(type: E.Type, _ keyPath: String, options: KeyValueObservingOptions) -> Observable<E?> {}
}
#endif
```
Expand Down
19 changes: 17 additions & 2 deletions RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ import Foundation.NSObject
import RxSwift
#endif

/// Key value observing options
public struct KeyValueObservingOptions: OptionSet {
/// Raw value
public let rawValue: UInt

public init(rawValue: UInt) {
self.rawValue = rawValue
}

/// Whether a sequence element should be sent to the observer immediately, before the subscribe method even returns.
public static let initial = KeyValueObservingOptions(rawValue: 1 << 0)
/// Whether to send updated values.
public static let new = KeyValueObservingOptions(rawValue: 1 << 1)
}

extension Reactive where Base: NSObject {

/**
Expand All @@ -23,7 +38,7 @@ extension Reactive where Base: NSObject {
For more information take a look at `observe` method.
*/
public func observe<E: KVORepresentable>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
public func observe<E: KVORepresentable>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
return observe(E.KVOType.self, keyPath, options: options, retainSelf: retainSelf)
.map(E.init)
}
Expand All @@ -37,7 +52,7 @@ extension Reactive where Base: NSObject {
For more information take a look at `observeWeakly` method.
*/
public func observeWeakly<E: KVORepresentable>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
public func observeWeakly<E: KVORepresentable>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
return observeWeakly(E.KVOType.self, keyPath, options: options)
.map(E.init)
}
Expand Down
4 changes: 2 additions & 2 deletions RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension Reactive where Base: NSObject {
For more information take a look at `observe` method.
*/
public func observe<E: RawRepresentable>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> where E.RawValue: KVORepresentable {
public func observe<E: RawRepresentable>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> where E.RawValue: KVORepresentable {
return observe(E.RawValue.KVOType.self, keyPath, options: options, retainSelf: retainSelf)
.map(E.init)
}
Expand All @@ -43,7 +43,7 @@ extension Reactive where Base: NSObject {
For more information take a look at `observeWeakly` method.
*/
public func observeWeakly<E: RawRepresentable>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial]) -> Observable<E?> where E.RawValue: KVORepresentable {
public func observeWeakly<E: RawRepresentable>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial]) -> Observable<E?> where E.RawValue: KVORepresentable {
return observeWeakly(E.RawValue.KVOType.self, keyPath, options: options)
.map(E.init)
}
Expand Down
30 changes: 22 additions & 8 deletions RxCocoa/Foundation/NSObject+Rx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ extension Reactive where Base: NSObject {
- parameter retainSelf: Retains self during observation if set `true`.
- returns: Observable sequence of objects on `keyPath`.
*/
public func observe<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
public func observe<E>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
return KVOObservable(object: base, keyPath: keyPath, options: options, retainTarget: retainSelf).asObservable()
}
}
Expand All @@ -89,7 +89,7 @@ extension Reactive where Base: NSObject {
- parameter options: KVO mechanism notification options.
- returns: Observable sequence of objects on `keyPath`.
*/
public func observeWeakly<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
public func observeWeakly<E>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
return observeWeaklyKeyPathFor(base, keyPath: keyPath, options: options)
.map { n in
return n as? E
Expand Down Expand Up @@ -332,7 +332,7 @@ fileprivate protocol KVOObservableProtocol {
var target: AnyObject { get }
var keyPath: String { get }
var retainTarget: Bool { get }
var options: NSKeyValueObservingOptions { get }
var options: KeyValueObservingOptions { get }
}

fileprivate final class KVOObserver
Expand All @@ -347,7 +347,7 @@ fileprivate final class KVOObserver
_ = Resources.incrementTotal()
#endif

super.init(target: parent.target, retainTarget: parent.retainTarget, keyPath: parent.keyPath, options: parent.options, callback: callback)
super.init(target: parent.target, retainTarget: parent.retainTarget, keyPath: parent.keyPath, options: parent.options.nsOptions, callback: callback)
self.retainSelf = self
}

Expand All @@ -372,10 +372,10 @@ fileprivate final class KVOObservable<Element>
var strongTarget: AnyObject?

var keyPath: String
var options: NSKeyValueObservingOptions
var options: KeyValueObservingOptions
var retainTarget: Bool

init(object: AnyObject, keyPath: String, options: NSKeyValueObservingOptions, retainTarget: Bool) {
init(object: AnyObject, keyPath: String, options: KeyValueObservingOptions, retainTarget: Bool) {
self.target = object
self.keyPath = keyPath
self.options = options
Expand Down Expand Up @@ -403,7 +403,7 @@ fileprivate final class KVOObservable<Element>

#if !DISABLE_SWIZZLING && !os(Linux)

fileprivate func observeWeaklyKeyPathFor(_ target: NSObject, keyPath: String, options: NSKeyValueObservingOptions) -> Observable<AnyObject?> {
fileprivate func observeWeaklyKeyPathFor(_ target: NSObject, keyPath: String, options: KeyValueObservingOptions) -> Observable<AnyObject?> {
let components = keyPath.components(separatedBy: ".").filter { $0 != "self" }

let observable = observeWeaklyKeyPathFor(target, keyPathSections: components, options: options)
Expand Down Expand Up @@ -440,10 +440,24 @@ fileprivate final class KVOObservable<Element>
}
}

fileprivate extension KeyValueObservingOptions {
fileprivate var nsOptions: NSKeyValueObservingOptions {
var result: UInt = 0
if self.contains(.new) {
result |= NSKeyValueObservingOptions.new.rawValue
}
if self.contains(.initial) {
result |= NSKeyValueObservingOptions.initial.rawValue
}

return NSKeyValueObservingOptions(rawValue: result)
}
}

fileprivate func observeWeaklyKeyPathFor(
_ target: NSObject,
keyPathSections: [String],
options: NSKeyValueObservingOptions
options: KeyValueObservingOptions
) -> Observable<AnyObject?> {

weak var weakTarget: AnyObject? = target
Expand Down
2 changes: 1 addition & 1 deletion Tests/RxCocoaTests/KVOObservableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ extension KVOObservableTests {
func test_New_And_Initial() {
let testClass = TestClass()

let os = testClass.rx.observe(String.self, "pr", options: NSKeyValueObservingOptions(rawValue: NSKeyValueObservingOptions.initial.rawValue | NSKeyValueObservingOptions.new.rawValue))
let os = testClass.rx.observe(String.self, "pr", options: [.initial, .new])

var latest: String?

Expand Down

0 comments on commit 43cf3b1

Please sign in to comment.