From fa5d9ec97ede988c686f5a608ec04a5dc32eb2bc Mon Sep 17 00:00:00 2001 From: Krunoslav Zaher Date: Sun, 12 Jul 2015 16:07:40 +0200 Subject: [PATCH] Fixes build for all schemes. --- RxCocoa/RxCocoa.xcodeproj/project.pbxproj | 3 +- RxCocoa/RxCocoa/Common/DelegateProxy.swift | 3 ++ .../RxCocoa/Common/DelegateProxyType.swift | 17 ------ .../Implementations/Deallocating.swift | 4 +- .../Implementations/KVOObservable.swift | 6 ++- .../Common/Observables/NSObject+Rx.swift | 7 ++- RxCocoa/RxCocoa/OSX/NSTextField+Rx.swift | 18 +++---- .../Proxies/RxScrollViewDelegateProxy.swift | 43 +++++++-------- RxCocoa/RxCocoa/iOS/UIActionSheet+Rx.swift | 6 +-- RxCocoa/RxCocoa/iOS/UIAlertView+Rx.swift | 6 +-- RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift | 2 +- RxCocoa/RxCocoa/iOS/UIControl+Rx.swift | 4 +- .../RxCocoa/iOS/UIGestureRecognizer+Rx.swift | 2 +- RxCocoa/RxCocoa/iOS/UIImageView+Rx.swift | 52 ++++++++++--------- RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift | 8 ++- RxTests/RxCocoaTests/KVOObservableTests.swift | 4 +- RxTests/RxCocoaTests/NSObject+RxTests.swift | 4 +- .../Tests/DelegateProxyTest.swift | 27 ++++++++++ RxTests/RxTests.xcodeproj/project.pbxproj | 4 +- 19 files changed, 116 insertions(+), 104 deletions(-) diff --git a/RxCocoa/RxCocoa.xcodeproj/project.pbxproj b/RxCocoa/RxCocoa.xcodeproj/project.pbxproj index e2c6f8c9..4816ec18 100644 --- a/RxCocoa/RxCocoa.xcodeproj/project.pbxproj +++ b/RxCocoa/RxCocoa.xcodeproj/project.pbxproj @@ -639,7 +639,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = "ENABLE_SWIZZLING=1"; + GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -649,7 +649,6 @@ INFOPLIST_FILE = RxCocoa/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.1; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_SWIFT_FLAGS = "-D ENABLE_SWIZZLING"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = ""; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/RxCocoa/RxCocoa/Common/DelegateProxy.swift b/RxCocoa/RxCocoa/Common/DelegateProxy.swift index 6b6fda59..f8329cf2 100644 --- a/RxCocoa/RxCocoa/Common/DelegateProxy.swift +++ b/RxCocoa/RxCocoa/Common/DelegateProxy.swift @@ -90,6 +90,9 @@ public class DelegateProxy : _RXDelegateProxy { } deinit { + for v in subjectsForSelector.values { + sendCompleted(v) + } #if TRACE_RESOURCES OSAtomicDecrement32(&resourceCount) #endif diff --git a/RxCocoa/RxCocoa/Common/DelegateProxyType.swift b/RxCocoa/RxCocoa/Common/DelegateProxyType.swift index 8d01a2be..3f1e4030 100644 --- a/RxCocoa/RxCocoa/Common/DelegateProxyType.swift +++ b/RxCocoa/RxCocoa/Common/DelegateProxyType.swift @@ -149,23 +149,6 @@ func installDelegate(proxy: P, delegate: AnyObject, retain } } -func proxyObservableForObject(object: AnyObject, - addObserver: (P, ObserverOf) -> DisposeKey, - removeObserver: (P, DisposeKey) -> ()) - -> Observable { - - return AnonymousObservable { observer in - let proxy: P = proxyForObject(object) - let key = addObserver(proxy, observer) - - return AnonymousDisposable { - MainScheduler.ensureExecutingOnScheduler() - - removeObserver(proxy, key) - } - } -} - func setProxyDataSourceForObject(object: AnyObject, dataSource: AnyObject, retainDataSource: Bool, binding: (P, Event) -> Void) -> Observable -> Disposable { return { source in diff --git a/RxCocoa/RxCocoa/Common/Observables/Implementations/Deallocating.swift b/RxCocoa/RxCocoa/Common/Observables/Implementations/Deallocating.swift index 3cb7eee3..ee5c8dcd 100644 --- a/RxCocoa/RxCocoa/Common/Observables/Implementations/Deallocating.swift +++ b/RxCocoa/RxCocoa/Common/Observables/Implementations/Deallocating.swift @@ -8,6 +8,7 @@ import Foundation +#if ENABLE_SWIZZLING class Deallocating : NSObject , RXDeallocating { typealias DeallocatingAction = () -> () @@ -21,4 +22,5 @@ class Deallocating : NSObject func deallocating() { deallocatingAction() } -} \ No newline at end of file +} +#endif diff --git a/RxCocoa/RxCocoa/Common/Observables/Implementations/KVOObservable.swift b/RxCocoa/RxCocoa/Common/Observables/Implementations/KVOObservable.swift index 0c8dd4be..150121d7 100644 --- a/RxCocoa/RxCocoa/Common/Observables/Implementations/KVOObservable.swift +++ b/RxCocoa/RxCocoa/Common/Observables/Implementations/KVOObservable.swift @@ -9,7 +9,6 @@ import Foundation import RxSwift - class KVOObservable : Producer , KVOObservableProtocol { unowned var target: AnyObject @@ -45,6 +44,8 @@ class KVOObservable : Producer } +#if ENABLE_SWIZZLING + func observeWeaklyKeyPathFor(target: NSObject, # keyPath: String, # options: NSKeyValueObservingOptions) -> Observable { let components = keyPath.componentsSeparatedByString(".").filter { $0 != "self" } @@ -137,4 +138,5 @@ func observeWeaklyKeyPathFor( } } >- switchLatest -} \ No newline at end of file +} +#endif diff --git a/RxCocoa/RxCocoa/Common/Observables/NSObject+Rx.swift b/RxCocoa/RxCocoa/Common/Observables/NSObject+Rx.swift index 4c02b452..66f54a98 100644 --- a/RxCocoa/RxCocoa/Common/Observables/NSObject+Rx.swift +++ b/RxCocoa/RxCocoa/Common/Observables/NSObject+Rx.swift @@ -54,8 +54,11 @@ extension NSObject { public func rx_observe(keyPath: String, options: NSKeyValueObservingOptions, retainSelf: Bool) -> Observable { return KVOObservable(object: self, keyPath: keyPath, options: options, retainTarget: retainSelf) } - +} + #if ENABLE_SWIZZLING +// KVO +extension NSObject { // Observes values on `keyPath` starting from `self` with `.Initial | .New` options. // Doesn't retain `self` and when `self` is deallocated, completes the sequence. public func rx_observeWeakly(keyPath: String) -> Observable { @@ -70,8 +73,8 @@ extension NSObject { return n as? Element } } -#endif } +#endif // Dealloc extension NSObject { diff --git a/RxCocoa/RxCocoa/OSX/NSTextField+Rx.swift b/RxCocoa/RxCocoa/OSX/NSTextField+Rx.swift index 2c683fe6..fbb72b18 100644 --- a/RxCocoa/RxCocoa/OSX/NSTextField+Rx.swift +++ b/RxCocoa/RxCocoa/OSX/NSTextField+Rx.swift @@ -13,22 +13,19 @@ import RxSwift class RxTextFieldDelegate : DelegateProxy , NSTextFieldDelegate , DelegateProxyType { - typealias Observer = ObserverOf - typealias DisposeKey = Bag.KeyType - - var observers: Bag = Bag() - let textField: NSTextField + let textSubject = ReplaySubject(bufferSize: 1) required init(parentObject: AnyObject) { self.textField = parentObject as! NSTextField super.init(parentObject: parentObject) + sendNext(self.textSubject, self.textField.stringValue) } override func controlTextDidChange(notification: NSNotification) { let textField = notification.object as! NSTextField let nextValue = textField.stringValue - dispatchNext(nextValue, observers) + sendNext(self.textSubject, nextValue) } class func currentDelegateFor(object: AnyObject) -> AnyObject? { @@ -67,11 +64,8 @@ extension NSTextField { } public var rx_text: Observable { - return proxyObservableForObject(self, { (p: RxTextFieldDelegate, o) in - sendNext(o, self.stringValue) - return p.observers.put(o) - }, { p, d in - p.observers.removeKey(d) - }) + let delegate = proxyForObject(self) as RxTextFieldDelegate + + return delegate.textSubject } } \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift b/RxCocoa/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift index ef322be0..3f590986 100644 --- a/RxCocoa/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift +++ b/RxCocoa/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift @@ -14,41 +14,30 @@ import UIKit class RxScrollViewDelegateProxy : DelegateProxy , UIScrollViewDelegate , DelegateProxyType { - typealias ContentOffsetObserver = ObserverOf - typealias ContentOffsetDisposeKey = Bag.KeyType + private var _contentOffsetSubject: ReplaySubject? - var contentOffsetObservers: Bag? - unowned let scrollView: UIScrollView + var contentOffsetSubject: Observable { + if _contentOffsetSubject == nil { + _contentOffsetSubject = ReplaySubject(bufferSize: 1) + sendNext(_contentOffsetSubject!, self.scrollView.contentOffset) + } + + return _contentOffsetSubject! + } + required init(parentObject: AnyObject) { self.scrollView = parentObject as! UIScrollView super.init(parentObject: parentObject) } - // registering / unregistering observers - - func addContentOffsetObserver(observer: ContentOffsetObserver) -> ContentOffsetDisposeKey { - MainScheduler.ensureExecutingOnScheduler() - if contentOffsetObservers == nil { - contentOffsetObservers = Bag() - } - return contentOffsetObservers!.put(observer) - } - - func removeContentOffsetObserver(key: ContentOffsetDisposeKey) { - MainScheduler.ensureExecutingOnScheduler() - - let element = contentOffsetObservers?.removeKey(key) - if element == nil { - removingObserverFailed() - } - } - // delegate methods func scrollViewDidScroll(scrollView: UIScrollView) { - dispatchNext(scrollView.contentOffset, contentOffsetObservers) + if let contentOffset = _contentOffsetSubject { + sendNext(contentOffset, self.scrollView.contentOffset) + } self._forwardToDelegate?.scrollViewDidScroll?(scrollView) } @@ -69,4 +58,10 @@ class RxScrollViewDelegateProxy : DelegateProxy let collectionView: UIScrollView = castOrFatalError(object) return collectionView.delegate } + + deinit { + if let contentOffset = _contentOffsetSubject { + sendCompleted(contentOffset) + } + } } \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/UIActionSheet+Rx.swift b/RxCocoa/RxCocoa/iOS/UIActionSheet+Rx.swift index b07fa049..18f5c0f0 100644 --- a/RxCocoa/RxCocoa/iOS/UIActionSheet+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIActionSheet+Rx.swift @@ -20,20 +20,20 @@ extension UIActionSheet { return rx_delegate.observe("actionSheet:clickedButtonAtIndex:") >- map { a in return a[1] as! Int - } + } } public var rx_willDismissWithButtonIndex: Observable { return rx_delegate.observe("actionSheet:willDismissWithButtonIndex:") >- map { a in return a[1] as! Int - } + } } public var rx_didDismissWithButtonIndex: Observable { return rx_delegate.observe("actionSheet:didDismissWithButtonIndex:") >- map { a in return a[1] as! Int - } + } } } \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/UIAlertView+Rx.swift b/RxCocoa/RxCocoa/iOS/UIAlertView+Rx.swift index 65db3525..c7e6f438 100644 --- a/RxCocoa/RxCocoa/iOS/UIAlertView+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIAlertView+Rx.swift @@ -20,20 +20,20 @@ extension UIAlertView { return rx_delegate.observe("alertView:clickedButtonAtIndex:") >- map { a in return a[1] as! Int - } + } } public var rx_willDismissWithButtonIndex: Observable { return rx_delegate.observe("alertView:willDismissWithButtonIndex:") >- map { a in return a[1] as! Int - } + } } public var rx_didDismissWithButtonIndex: Observable { return rx_delegate.observe("alertView:didDismissWithButtonIndex:") >- map { a in return a[1] as! Int - } + } } } diff --git a/RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift b/RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift index 8b91f2b5..df150269 100644 --- a/RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift @@ -17,7 +17,7 @@ extension UIBarButtonItem { sendNext(observer, ()) } return target - } + } >- takeUntil(rx_deallocated) } } diff --git a/RxCocoa/RxCocoa/iOS/UIControl+Rx.swift b/RxCocoa/RxCocoa/iOS/UIControl+Rx.swift index b58e181f..57990009 100644 --- a/RxCocoa/RxCocoa/iOS/UIControl+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIControl+Rx.swift @@ -23,7 +23,7 @@ extension UIControl { return AnonymousDisposable { controlTarget.dispose() } - } + } >- takeUntil(rx_deallocated) } func rx_value(getValue: () -> T) -> Observable { @@ -38,7 +38,7 @@ extension UIControl { return AnonymousDisposable { controlTarget.dispose() } - } + } >- takeUntil(rx_deallocated) } public func rx_subscribeEnabledTo(source: Observable) -> Disposable { diff --git a/RxCocoa/RxCocoa/iOS/UIGestureRecognizer+Rx.swift b/RxCocoa/RxCocoa/iOS/UIGestureRecognizer+Rx.swift index 26d066a1..cdc8d237 100644 --- a/RxCocoa/RxCocoa/iOS/UIGestureRecognizer+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIGestureRecognizer+Rx.swift @@ -65,7 +65,7 @@ extension UIGestureRecognizer { } return observer - } + } >- takeUntil(rx_deallocated) } } \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/UIImageView+Rx.swift b/RxCocoa/RxCocoa/iOS/UIImageView+Rx.swift index 9fd51d3f..36ad50b4 100644 --- a/RxCocoa/RxCocoa/iOS/UIImageView+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIImageView+Rx.swift @@ -12,35 +12,37 @@ import UIKit extension UIImageView { public func rx_subscribeImageTo(source: Observable) -> Disposable { - return rx_subscribeImageTo(false)(source: source) + return rx_subscribeImageTo(false)(source) } public func rx_subscribeImageTo (animated: Bool) - (source: Observable) -> Disposable { - return source.subscribe(AnonymousObserver { event in - MainScheduler.ensureExecutingOnScheduler() - - switch event { - case .Next(let boxedValue): - let value = boxedValue.value - if animated && value != nil { - let transition = CATransition() - transition.duration = 0.25 - transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - transition.type = kCATransitionFade - self.layer.addAnimation(transition, forKey: kCATransition) + -> Observable -> Disposable { + return { source in + return source.subscribe(AnonymousObserver { event in + MainScheduler.ensureExecutingOnScheduler() + + switch event { + case .Next(let boxedValue): + let value = boxedValue.value + if animated && value != nil { + let transition = CATransition() + transition.duration = 0.25 + transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + transition.type = kCATransitionFade + self.layer.addAnimation(transition, forKey: kCATransition) + } + else { + self.layer.removeAllAnimations() + } + self.image = value + case .Error(let error): + bindingErrorToInterface(error) + break + case .Completed: + break } - else { - self.layer.removeAllAnimations() - } - self.image = value - case .Error(let error): - bindingErrorToInterface(error) - break - case .Completed: - break - } - }) + }) + } } } \ No newline at end of file diff --git a/RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift b/RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift index a1844ecf..00483faf 100644 --- a/RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift +++ b/RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift @@ -27,11 +27,9 @@ extension UIScrollView { // properties public var rx_contentOffset: Observable { - return proxyObservableForObject(self, { (b: RxScrollViewDelegateProxy, o) in - return b.addContentOffsetObserver(o) - }, { (b, d) -> () in - b.removeContentOffsetObserver(d) - }) + let proxy = proxyForObject(self) as RxScrollViewDelegateProxy + + return proxy.contentOffsetSubject } // delegate diff --git a/RxTests/RxCocoaTests/KVOObservableTests.swift b/RxTests/RxCocoaTests/KVOObservableTests.swift index 100b7c43..318c9ca1 100644 --- a/RxTests/RxCocoaTests/KVOObservableTests.swift +++ b/RxTests/RxCocoaTests/KVOObservableTests.swift @@ -253,6 +253,7 @@ extension KVOObservableTests { } } +#if ENABLE_SWIZZLING // test weak observe extension KVOObservableTests { @@ -788,4 +789,5 @@ extension KVOObservableTests { XCTAssertTrue(rootDeallocated) } -} \ No newline at end of file +} +#endif diff --git a/RxTests/RxCocoaTests/NSObject+RxTests.swift b/RxTests/RxCocoaTests/NSObject+RxTests.swift index 6d9f6e63..89e9b588 100644 --- a/RxTests/RxCocoaTests/NSObject+RxTests.swift +++ b/RxTests/RxCocoaTests/NSObject+RxTests.swift @@ -79,6 +79,7 @@ extension NSObjectTests { } } +#if ENABLE_SWIZZLING // rx_deallocating extension NSObjectTests { func testDeallocating_ObservableFires() { @@ -141,4 +142,5 @@ extension NSObjectTests { XCTAssertFalse(fired) } -} \ No newline at end of file +} +#endif diff --git a/RxTests/RxSwiftTests/Tests/DelegateProxyTest.swift b/RxTests/RxSwiftTests/Tests/DelegateProxyTest.swift index 9479a5db..af569979 100644 --- a/RxTests/RxSwiftTests/Tests/DelegateProxyTest.swift +++ b/RxTests/RxSwiftTests/Tests/DelegateProxyTest.swift @@ -223,4 +223,31 @@ class DelegateProxyTest : RxTest { XCTAssertEqual(mock.messages, []) } + + func test_delegateProxyCompletesOnDealloc() { + var view: ThreeDSectionedView! = ThreeDSectionedView() + let mock = MockThreeDSectionedViewProtocol() + + view.delegate = mock + + let completed = RxMutableBox(false) + + autoreleasepool { + XCTAssertTrue(!mock.respondsToSelector("threeDView(threeDView:didGetXXX:")) + + let sentArgument = NSIndexPath(index: 0) + + var receivedArgument: NSIndexPath? = nil + + view.rx_proxy.observe("threeDView:didGetXXX:") + >- subscribeCompleted { + completed.value = true + } + + view.delegate?.threeDView?(view, didGetXXX: sentArgument) + } + XCTAssertTrue(!completed.value) + view = nil + XCTAssertTrue(completed.value) + } } \ No newline at end of file diff --git a/RxTests/RxTests.xcodeproj/project.pbxproj b/RxTests/RxTests.xcodeproj/project.pbxproj index 4fa4bea5..fafabf6d 100644 --- a/RxTests/RxTests.xcodeproj/project.pbxproj +++ b/RxTests/RxTests.xcodeproj/project.pbxproj @@ -490,7 +490,7 @@ "-framework", XCTest, ); - OTHER_SWIFT_FLAGS = "-D DEBUG -D TRACE_RESOURCES"; + OTHER_SWIFT_FLAGS = "-D DEBUG -D TRACE_RESOURCES -D ENABLE_SWIZZLING"; PRODUCT_NAME = RxTests; }; name = Debug; @@ -599,7 +599,7 @@ "-framework", XCTest, ); - OTHER_SWIFT_FLAGS = "-D TRACE_RESOURCES"; + OTHER_SWIFT_FLAGS = "-D TRACE_RESOURCES -D ENABLE_SWIZZLING"; PRODUCT_NAME = RxTests; }; name = "Release-Tests";