将 UIApplicationDelegate 方法转换为 RxSwift Observables

Posted

技术标签:

【中文标题】将 UIApplicationDelegate 方法转换为 RxSwift Observables【英文标题】:Transform UIApplicationDelegate methods into RxSwift Observables 【发布时间】:2016-02-23 10:44:09 【问题描述】:

在 RxSwift / RxCocoa 中,您可以为委托创建反应式包装器(例如 UIScrollViewDelegateCLLocationManagerDelegate),以便为某些委托方法启用 Rx 可观察序列。

我正在尝试为UIApplicationDelegate 方法applicationDidBecomeActive: 实现此功能

到目前为止,我尝试的非常简单,类似于 RxCocoa 中包含的 DelegateProxy 子类。

我创建了我的DelegateProxy 子类:

class RxUIApplicationDelegateProxy: DelegateProxy, UIApplicationDelegate, DelegateProxyType 

    static func currentDelegateFor(object: AnyObject) -> AnyObject? 
        let application: UIApplication = object as! UIApplication
        return application.delegate
    

    static func setCurrentDelegate(delegate: AnyObject?, toObject object: AnyObject) 
        let application: UIApplication = object as! UIApplication
        application.delegate = delegate as? UIApplicationDelegate
    

还有UIApplication 的 Rx 扩展:

extension UIApplication 
    public var rx_delegate: DelegateProxy 
        return proxyForObject(RxUIApplicationDelegateProxy.self, self)
    

    public var rx_applicationDidBecomeActive: Observable<Void> 
        return rx_delegate.observe("applicationDidBecomeActive:")
            .map  _ in
                return
            
    

在我的 AppDelegate 中,我订阅了 observable:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    // the usual setup
    // and then:
    application.rx_applicationDidBecomeActive
        .subscribeNext  _ in
            print("Active!")
        
        .addDisposableTo(disposeBag)

    return true

当我启动我的应用程序时“活动!”被打印出来,然后我在 RxCocoa 的 _RXDelegateProxy_ 类中遇到以下崩溃:

有人知道问题可能是什么吗?或者有没有人成功实现过rx_applicationDidBecomeActive之类的东西?

【问题讨论】:

aSelector 到底是什么? aSelector = (SEL) "window" 【参考方案1】:

RxSwift 和内存管理似乎是一个非常棘手的问题。

DelegateProxyType 的默认实现将委托代理的实例(在本例中为 RxUIApplicationDelegateProxy)设置为 delegateUIApplication

它还将原始AppDelegate 存储为一个名为forwardToDelegate 的属性,因此仍然可以将所有委托方法传递给它。

问题是,当设置新的应用委托时:

 application.delegate = delegate as? UIApplicationDelegate

原来的被释放了!您可以通过在AppDelegate 中覆盖deinit 来检查它。原因在this answer 中有解释。因为属性forwardToDelegate 的类型是assign,所以当属性指向一个已释放的对象时,您的应用程序会崩溃。

我已经找到了解决方法。我不确定这是否是推荐的方式,所以请注意。您可以在RxUIApplicationDelegateProxy 中覆盖来自DelegateProxyType 的方法:

  override func setForwardToDelegate(delegate: AnyObject?, retainDelegate: Bool) 
    super.setForwardToDelegate(delegate, retainDelegate: true)
  

在正常情况下,您不希望保留委托,因为它会导致保留周期。但在这种特殊情况下,这不是问题:您的 UIApplication 对象将一直存在,而您的应用程序仍然存在。

【讨论】:

您建议的解决方案确实解决了问题。非常感谢您花时间查找并解释问题!

以上是关于将 UIApplicationDelegate 方法转换为 RxSwift Observables的主要内容,如果未能解决你的问题,请参考以下文章

什么是 Cordova 的 UIApplicationDelegate 等价物

如何在整个程序中使用 UIApplicationDelegate?

如何在命令行 GHUnit 中使用 UIApplicationDelegate?

UIApplicationDelegate 与 NSApplicationDelegate、MainMenu.xib

为我的自定义 UIApplicationDelegate 绕过 UABaseAppDelegateSurrogate

UIApplication对象及其代理UIApplicationDelegate[转]