Repository: ReactiveX/RxSwift
File: RxCocoa/Common/Observables/NSObject+Rx.swift (Swift)

Code before:
//
//  NSObject+Rx.swift
//  RxCocoa
//
//  Created by Krunoslav Zaher on 2/21/15.
//  Copyright © 2015 Krunoslav Zaher. All rights reserved.
//

import Foundation
#if !RX_NO_MODULE
import RxSwift
#endif

#if !DISABLE_SWIZZLING
var deallocatingSubjectTriggerContext: UInt8 = 0
var deallocatingSubjectContext: UInt8 = 0
#endif
var deallocatedSubjectTriggerContext: UInt8 = 0
var deallocatedSubjectContext: UInt8 = 0

/**
KVO is a tricky mechanism.

When observing child in a ownership hierarchy, usually retaining observing target is wanted behavior.
When observing parent in a ownership hierarchy, usually retaining target isn't wanter behavior.

KVO with weak references is especially tricky. For it to work, some kind of swizzling is required.
That can be done by
    * replacing object class dynamically (like KVO does)
    * by swizzling `dealloc` method on all instances for a class.
    * some third method ...

Both approaches can fail in certain scenarios:
    * problems arise when swizzlers return original object class (like KVO does when nobody is observing)
    * Problems can arise because replacing dealloc method isn't atomic operation (get implementation,
    set implementation).

Second approach is chosen. It can fail in case there are multiple libraries dynamically trying
to replace dealloc method. In case that isn't the case, it should be ok.
*/
extension NSObject {


    /**
     Observes values on `keyPath` starting from `self` with `options` and retains `self` if `retainSelf` is set.

     `rx_observe` is just a simple and performant wrapper around KVO mechanism.

     * it can be used to observe paths starting from `self` or from ancestors in ownership graph (`retainSelf = false`)
     * it can be used to observe paths starting from descendants in ownership graph (`retainSelf = true`)
     * the paths have to consist only of `strong` properties, otherwise you are risking crashing the system by not unregistering KVO observer before dealloc.

     If support for weak properties is needed or observing arbitrary or unknown relationships in the
     ownership tree, `rx_observeWeakly` is the preferred option.

     - parameter keyPath: Key path of property names to observe.
     - parameter options: KVO mechanism notification options.
     - parameter retainSelf: Retains self during observation if set `true`.
     - returns: Observable sequence of objects on `keyPath`.
     */
    // @warn_unused_result(message:"http://git.io/rxs.uo")
    public func rx_observe<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
        return KVOObservable(object: self, keyPath: keyPath, options: options, retainTarget: retainSelf).asObservable()
    }
}

#if !DISABLE_SWIZZLING
// KVO
extension NSObject {
    /**
     Observes values on `keyPath` starting from `self` with `options` and doesn't retain `self`.

     It can be used in all cases where `rx_observe` can be used and additionally

     * because it won't retain observed target, it can be used to observe arbitrary object graph whose ownership relation is unknown
     * it can be used to observe `weak` properties

     **Since it needs to intercept object deallocation process it needs to perform swizzling of `dealloc` method on observed object.**

     - parameter keyPath: Key path of property names to observe.
     - parameter options: KVO mechanism notification options.
     - returns: Observable sequence of objects on `keyPath`.
     */
    // @warn_unused_result(message:"http://git.io/rxs.uo")
    public func rx_observeWeakly<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
        return observeWeaklyKeyPathFor(self, keyPath: keyPath, options: options)
            .map { n in
                return n as? E
            }
    }
}
#endif

// Dealloc
extension NSObject {
    
    /**
    Observable sequence of object deallocated events.
    
    After object is deallocated one `()` element will be produced and sequence will immediately complete.
    
    - returns: Observable sequence of object deallocated events.
    */
    public var rx_deallocated: Observable<Void> {
        return rx_synchronized {
            if let deallocObservable = objc_getAssociatedObject(self, &deallocatedSubjectContext) as? DeallocObservable {
                return deallocObservable._subject
            }

            let deallocObservable = DeallocObservable()

            objc_setAssociatedObject(self, &deallocatedSubjectContext, deallocObservable, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            return deallocObservable._subject
        }
    }

#if !DISABLE_SWIZZLING

    /**
     Observable sequence of message arguments that completes when object is deallocated.

     In case an error occurs sequence will fail with `RxCocoaObjCRuntimeError`.
     
     In case some argument is `nil`, instance of `NSNull()` will be sent.

     - returns: Observable sequence of object deallocating events.
     */
    public func rx_sentMessage(_ selector: Selector) -> Observable<[AnyObject]> {
        return Observable.create { _ in
            return AnonymousDisposable {}
        }
        /*
        return rx_synchronized {
            // in case of dealloc selector replay subject behavior needs to be used
            if selector == deallocSelector {
                return rx_deallocating.map { _ in [] }
            }

            let rxSelector = RX_selector(selector)
            let selectorReference = RX_reference_from_selector(rxSelector)

            let subject: MessageSentObservable
            if let existingSubject = objc_getAssociatedObject(self, selectorReference) as? MessageSentObservable {
                subject = existingSubject
            }
            else {
                subject = MessageSentObservable()
                objc_setAssociatedObject(
                    self,
                    selectorReference,
                    subject,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }

            if subject.isActive {
                return subject.asObservable()
            }

            var error: NSError?
            guard let targetImplementation = RX_ensure_observing(self, selector, &error) else {
                return Observable.error(error?.rxCocoaErrorForTarget(self) ?? RxCocoaError.unknown)
            }

            subject.targetImplementation = targetImplementation
            return subject.asObservable()
        }*/
    }

    /**
    Observable sequence of object deallocating events.
    
    When `dealloc` message is sent to `self` one `()` element will be produced and after object is deallocated sequence
    will immediately complete.
     
    In case an error occurs sequence will fail with `RxCocoaObjCRuntimeError`.
    
    - returns: Observable sequence of object deallocating events.
    */
    public var rx_deallocating: Observable<()> {
        return Observable.create { _ in
            return AnonymousDisposable {}
        }
        /*
        return rx_synchronized {

            let subject: DeallocatingObservable
            if let existingSubject = objc_getAssociatedObject(self, rxDeallocatingSelectorReference) as? DeallocatingObservable {
                subject = existingSubject
            }
            else {
                subject = DeallocatingObservable()
                objc_setAssociatedObject(
                    self,
                    rxDeallocatingSelectorReference,
                    subject,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }

            if subject.isActive {
                return subject.asObservable()
            }

            var error: NSError?
            let targetImplementation = RX_ensure_observing(self, deallocSelector, &error)
            if targetImplementation == nil {
                return Observable.error(error?.rxCocoaErrorForTarget(self) ?? RxCocoaError.unknown)
            }

            subject.targetImplementation = targetImplementation!
            return subject.asObservable()
        }*/
    }
#endif
}

let deallocSelector = NSSelectorFromString("dealloc")
let rxDeallocatingSelector = RX_selector(deallocSelector)
let rxDeallocatingSelectorReference = RX_reference_from_selector(rxDeallocatingSelector)

extension NSObject {
    func rx_synchronized<T>( _ action: @noescape() -> T) -> T {
        objc_sync_enter(self)
        let result = action()
        objc_sync_exit(self)
        return result
    }
}

extension NSObject {
    /**
     Helper to make sure that `Observable` returned from `createCachedObservable` is only created once.
     This is important because there is only one `target` and `action` properties on `NSControl` or `UIBarButtonItem`.
     */
    func rx_lazyInstanceObservable<T: AnyObject>(_ key: UnsafePointer<Void>, createCachedObservable: () -> T) -> T {
        if let value = objc_getAssociatedObject(self, key) {
            return value as! T
        }
        
        let observable = createCachedObservable()
        
        objc_setAssociatedObject(self, key, observable, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        
        return observable
    }
}


Review comment (bug):
Here also causes an error.

```
CompileSwift normal arm64 /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx.swift
    cd /Users/XXXXX/Workspace/RxSwift
    /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISlider+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIScrollView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIPickerView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Operators.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/DelegateProxyType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxTarget.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxImagePickerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITextView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxCollectionViewDataSourceProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ControlProperty+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ControlEvent+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTextStorageDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxCocoa.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIRefreshControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIStepper+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIImageView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/ControlEvent.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx+RawRepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/SectionedViewDataSourceType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Variable+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISearchController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITableView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxSearchControllerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/KVOObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIAlertAction+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxTextInput.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UILabel+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UINavigationItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIPageControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxSearchBarDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ObservableConvertibleType+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITabBarItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIApplication+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/DeallocObservable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observable+Bind.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISegmentedControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/KVOObservable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Reactive.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIProgressView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIViewController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable+Swift.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Operators+arity.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIButton+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CLLocationManager+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver.swift -primary-file /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/NSTextStorage+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIBarButtonItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/MessageSentObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/ControlProperty.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIDatePicker+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTableViewDataSourceProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/NSLayoutConstraint+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIGestureRecognizer+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/DelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITabBar+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Proxies/RxCLLocationManagerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTabBarDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISwitch+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIImagePickerController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx+KVORepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Logging.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UICollectionView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Protocols/RxCollectionViewDataSourceType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSNotificationCenter+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITextField+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSURLSession+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/ControlTarget.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISearchBar+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Events/ItemEvents.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable+CoreGraphics.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Protocols/RxTableViewDataSourceType.swift -target arm64-apple-ios8.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk -I /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos -F /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos -application-extension -enable-testing -g -import-underlying-module -module-cache-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/ModuleCache -D TRACE_RESOURCES -D DEBUG -serialize-debugging-options -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/swift-overrides.hmap -Xcc -iquote -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-generated-files.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-own-target-headers.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-all-non-framework-target-headers.hmap -Xcc -ivfsoverlay -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/all-product-headers.yaml -Xcc -iquote -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-project-headers.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos/include -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/DerivedSources/arm64 -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/DerivedSources -Xcc -DDEBUG=1 -Xcc -DTRACE_RESOURCES=1 -Xcc -ivfsoverlay -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/unextended-module-overlay.yaml -Xcc -working-directory/Users/XXXXX/Workspace/RxSwift -emit-module-doc-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx~partial.swiftdoc -Onone -module-name RxCocoa -emit-module-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx~partial.swiftmodule -serialize-diagnostics-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.dia -emit-dependencies-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.d -emit-reference-dependencies-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.swiftdeps -o /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.o -embed-bitcode-marker
0  swift                    0x00000001051b5e3d PrintStackTraceSignalHandler(void*) + 45
1  swift                    0x00000001051b5886 SignalHandler(int) + 470
2  libsystem_platform.dylib 0x00007fff85e9352a _sigtramp + 26
3  libsystem_platform.dylib 000000000000000000 _sigtramp + 2048314096
4  swift                    0x00000001025cae7a swift::irgen::IRGenDebugInfo::setCurrentLoc(swift::irgen::IRBuilder&, swift::SILDebugScope const*, llvm::Optional<swift::SILLocation>) + 282
5  swift                    0x00000001025d67d1 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 7041
6  swift                    0x00000001024fd220 swift::irgen::IRGenerator::emitLazyDefinitions() + 5152
7  swift                    0x00000001025bcc1b performIRGeneration(swift::IRGenOptions&, swift::ModuleDecl*, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, unsigned int) + 1723
8  swift                    0x000000010248b337 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*) + 23015
9  swift                    0x0000000102483679 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 18137
10 swift                    0x00000001024404a0 main + 10240
11 libdyld.dylib            0x00007fff859055ad start + 1
12 libdyld.dylib            0x00000000000000a1 start + 2054138613
Stack dump:
0.  Program arguments: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISlider+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIScrollView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIPickerView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Operators.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/DelegateProxyType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxTarget.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxImagePickerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITextView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxCollectionViewDataSourceProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ControlProperty+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ControlEvent+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTextStorageDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxCocoa.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIRefreshControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIStepper+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIImageView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/ControlEvent.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx+RawRepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/SectionedViewDataSourceType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Variable+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISearchController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITableView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxSearchControllerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/KVOObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIAlertAction+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/RxTextInput.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UILabel+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UINavigationItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIPageControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxSearchBarDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/ObservableConvertibleType+Driver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITabBarItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIApplication+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Subscription.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/DeallocObservable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observable+Bind.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISegmentedControl+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/KVOObservable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Reactive.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIProgressView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIViewController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable+Swift.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver+Operators+arity.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIButton+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CLLocationManager+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/Driver/Driver.swift -primary-file /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/NSTextStorage+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIBarButtonItem+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/MessageSentObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/ControlProperty.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIDatePicker+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTableViewDataSourceProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/NSLayoutConstraint+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIGestureRecognizer+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/DelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITabBar+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Proxies/RxCLLocationManagerDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Proxies/RxTabBarDelegateProxy.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISwitch+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UIImagePickerController+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx+KVORepresentable.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Logging.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UICollectionView+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Protocols/RxCollectionViewDataSourceType.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSNotificationCenter+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UITextField+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSURLSession+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/Implementations/ControlTarget.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/UISearchBar+Rx.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Events/ItemEvents.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/KVORepresentable+CoreGraphics.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/CocoaUnits/UIBindingObserver.swift /Users/XXXXX/Workspace/RxSwift/RxCocoa/iOS/Protocols/RxTableViewDataSourceType.swift -target arm64-apple-ios8.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.0.sdk -I /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos -F /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos -application-extension -enable-testing -g -import-underlying-module -module-cache-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/ModuleCache -D TRACE_RESOURCES -D DEBUG -serialize-debugging-options -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/swift-overrides.hmap -Xcc -iquote -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-generated-files.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-own-target-headers.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-all-non-framework-target-headers.hmap -Xcc -ivfsoverlay -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/all-product-headers.yaml -Xcc -iquote -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/RxCocoa-project-headers.hmap -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Products/Debug-iphoneos/include -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/DerivedSources/arm64 -Xcc -I/Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/DerivedSources -Xcc -DDEBUG=1 -Xcc -DTRACE_RESOURCES=1 -Xcc -ivfsoverlay -Xcc /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/unextended-module-overlay.yaml -Xcc -working-directory/Users/XXXXX/Workspace/RxSwift -emit-module-doc-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx~partial.swiftdoc -Onone -module-name RxCocoa -emit-module-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx~partial.swiftmodule -serialize-diagnostics-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.dia -emit-dependencies-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.d -emit-reference-dependencies-path /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.swiftdeps -o /Users/XXXXX/Library/Developer/Xcode/DerivedData/Rx-cjudovxsdfkcnyctzmjtirtbpnbd/Build/Intermediates/Rx.build/Debug-iphoneos/RxCocoa-iOS.build/Objects-normal/arm64/NSObject+Rx.o -embed-bitcode-marker 
1.  While emitting IR SIL function @_TFFE7RxCocoaCSo8NSObject14rx_sentMessageFV10ObjectiveC8SelectorGC7RxSwift10ObservableGSaPs9AnyObject___U_FT_GS4_GSaPS5____ for expression at [/Users/XXXXX/Workspace/RxSwift/RxCocoa/Common/Observables/NSObject+Rx.swift:129:32 - line:163:9] RangeText="{
            // in case of dealloc selector replay subject behavior needs to be used
            if selector == deallocSelector {
                return rx_deallocating.map { _ in [] }
            }

            let rxSelector = RX_selector(selector)
            let selectorReference = RX_reference_from_selector(rxSelector)

            let subject: MessageSentObservable
            if let existingSubject = objc_getAssociatedObject(self, selectorReference) as? MessageSentObservable {
                subject = existingSubject
            }
            else {
                subject = MessageSentObservable()
                objc_setAssociatedObject(
                    self,
                    selectorReference,
                    subject,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }

            if subject.isActive {
                return subject.asObservable()
            }

            var error: NSError?
            guard let targetImplementation = RX_ensure_observing(self, selector, &error) else {
                return Observable.error(error?.rxCocoaErrorForTarget(self) ?? RxCocoaError.unknown)
            }

            subject.targetImplementation = targetImplementation
            return subject.asObservable()
        }"
```


Code after:
//
//  NSObject+Rx.swift
//  RxCocoa
//
//  Created by Krunoslav Zaher on 2/21/15.
//  Copyright © 2015 Krunoslav Zaher. All rights reserved.
//

import Foundation
#if !RX_NO_MODULE
import RxSwift
#endif

#if !DISABLE_SWIZZLING
var deallocatingSubjectTriggerContext: UInt8 = 0
var deallocatingSubjectContext: UInt8 = 0
#endif
var deallocatedSubjectTriggerContext: UInt8 = 0
var deallocatedSubjectContext: UInt8 = 0

/**
KVO is a tricky mechanism.

When observing child in a ownership hierarchy, usually retaining observing target is wanted behavior.
When observing parent in a ownership hierarchy, usually retaining target isn't wanter behavior.

KVO with weak references is especially tricky. For it to work, some kind of swizzling is required.
That can be done by
    * replacing object class dynamically (like KVO does)
    * by swizzling `dealloc` method on all instances for a class.
    * some third method ...

Both approaches can fail in certain scenarios:
    * problems arise when swizzlers return original object class (like KVO does when nobody is observing)
    * Problems can arise because replacing dealloc method isn't atomic operation (get implementation,
    set implementation).

Second approach is chosen. It can fail in case there are multiple libraries dynamically trying
to replace dealloc method. In case that isn't the case, it should be ok.
*/
extension NSObject {


    /**
     Observes values on `keyPath` starting from `self` with `options` and retains `self` if `retainSelf` is set.

     `rx_observe` is just a simple and performant wrapper around KVO mechanism.

     * it can be used to observe paths starting from `self` or from ancestors in ownership graph (`retainSelf = false`)
     * it can be used to observe paths starting from descendants in ownership graph (`retainSelf = true`)
     * the paths have to consist only of `strong` properties, otherwise you are risking crashing the system by not unregistering KVO observer before dealloc.

     If support for weak properties is needed or observing arbitrary or unknown relationships in the
     ownership tree, `rx_observeWeakly` is the preferred option.

     - parameter keyPath: Key path of property names to observe.
     - parameter options: KVO mechanism notification options.
     - parameter retainSelf: Retains self during observation if set `true`.
     - returns: Observable sequence of objects on `keyPath`.
     */
    // @warn_unused_result(message:"http://git.io/rxs.uo")
    public func rx_observe<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> {
        return KVOObservable(object: self, keyPath: keyPath, options: options, retainTarget: retainSelf).asObservable()
    }
}

#if !DISABLE_SWIZZLING
// KVO
extension NSObject {
    /**
     Observes values on `keyPath` starting from `self` with `options` and doesn't retain `self`.

     It can be used in all cases where `rx_observe` can be used and additionally

     * because it won't retain observed target, it can be used to observe arbitrary object graph whose ownership relation is unknown
     * it can be used to observe `weak` properties

     **Since it needs to intercept object deallocation process it needs to perform swizzling of `dealloc` method on observed object.**

     - parameter keyPath: Key path of property names to observe.
     - parameter options: KVO mechanism notification options.
     - returns: Observable sequence of objects on `keyPath`.
     */
    // @warn_unused_result(message:"http://git.io/rxs.uo")
    public func rx_observeWeakly<E>(_ type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions = [.new, .initial]) -> Observable<E?> {
        return observeWeaklyKeyPathFor(self, keyPath: keyPath, options: options)
            .map { n in
                return n as? E
            }
    }
}
#endif

// Dealloc
extension NSObject {
    
    /**
    Observable sequence of object deallocated events.
    
    After object is deallocated one `()` element will be produced and sequence will immediately complete.
    
    - returns: Observable sequence of object deallocated events.
    */
    public var rx_deallocated: Observable<Void> {
        return rx_synchronized {
            if let deallocObservable = objc_getAssociatedObject(self, &deallocatedSubjectContext) as? DeallocObservable {
                return deallocObservable._subject
            }

            let deallocObservable = DeallocObservable()

            objc_setAssociatedObject(self, &deallocatedSubjectContext, deallocObservable, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            return deallocObservable._subject
        }
    }

#if !DISABLE_SWIZZLING

    /**
     Observable sequence of message arguments that completes when object is deallocated.

     In case an error occurs sequence will fail with `RxCocoaObjCRuntimeError`.
     
     In case some argument is `nil`, instance of `NSNull()` will be sent.

     - returns: Observable sequence of object deallocating events.
     */
    public func rx_sentMessage(_ selector: Selector) -> Observable<[AnyObject]> {
        return rx_synchronized {
            // in case of dealloc selector replay subject behavior needs to be used
            if selector == deallocSelector {
                return rx_deallocating.map { _ in [] }
            }

            let rxSelector = RX_selector(selector)
            let selectorReference = RX_reference_from_selector(rxSelector)

            let subject: MessageSentObservable
            if let existingSubject = objc_getAssociatedObject(self, selectorReference) as? MessageSentObservable {
                subject = existingSubject
            }
            else {
                subject = MessageSentObservable()
                objc_setAssociatedObject(
                    self,
                    selectorReference,
                    subject,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }

            if subject.isActive {
                return subject.asObservable()
            }

            var error: NSError?
            guard let targetImplementation = RX_ensure_observing(self, selector, &error) else {
                return Observable.error(error?.rxCocoaErrorForTarget(self) ?? RxCocoaError.unknown)
            }

            subject.targetImplementation = targetImplementation
            return subject.asObservable()
        }
    }

    /**
    Observable sequence of object deallocating events.
    
    When `dealloc` message is sent to `self` one `()` element will be produced and after object is deallocated sequence
    will immediately complete.
     
    In case an error occurs sequence will fail with `RxCocoaObjCRuntimeError`.
    
    - returns: Observable sequence of object deallocating events.
    */
    public var rx_deallocating: Observable<()> {
        return rx_synchronized {

            let subject: DeallocatingObservable
            if let existingSubject = objc_getAssociatedObject(self, rxDeallocatingSelectorReference) as? DeallocatingObservable {
                subject = existingSubject
            }
            else {
                subject = DeallocatingObservable()
                objc_setAssociatedObject(
                    self,
                    rxDeallocatingSelectorReference,
                    subject,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }

            if subject.isActive {
                return subject.asObservable()
            }

            var error: NSError?
            let targetImplementation = RX_ensure_observing(self, deallocSelector, &error)
            if targetImplementation == nil {
                return Observable.error(error?.rxCocoaErrorForTarget(self) ?? RxCocoaError.unknown)
            }

            subject.targetImplementation = targetImplementation!
            return subject.asObservable()
        }
    }
#endif
}

let deallocSelector = NSSelectorFromString("dealloc")
let rxDeallocatingSelector = RX_selector(deallocSelector)
let rxDeallocatingSelectorReference = RX_reference_from_selector(rxDeallocatingSelector)

extension NSObject {
    func rx_synchronized<T>( _ action: @noescape() -> T) -> T {
        objc_sync_enter(self)
        let result = action()
        objc_sync_exit(self)
        return result
    }
}

extension NSObject {
    /**
     Helper to make sure that `Observable` returned from `createCachedObservable` is only created once.
     This is important because there is only one `target` and `action` properties on `NSControl` or `UIBarButtonItem`.
     */
    func rx_lazyInstanceObservable<T: AnyObject>(_ key: UnsafePointer<Void>, createCachedObservable: () -> T) -> T {
        if let value = objc_getAssociatedObject(self, key) {
            return value as! T
        }
        
        let observable = createCachedObservable()
        
        objc_setAssociatedObject(self, key, observable, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        
        return observable
    }
}