6

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

我正在尝试为该UIApplicationDelegate方法实现这个applicationDidBecomeActive:

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

我创建了我的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
    }
}

和一个 Rx 扩展UIApplication

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

4

1 回答 1

9

RxSwift 和内存管理看起来是一个非常棘手的问题。

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

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

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

 application.delegate = delegate as? UIApplicationDelegate

原来的被释放了!您可以通过覆盖来检查deinitAppDelegate这个答案解释了原因。并且因为该属性forwardToDelegate是 type assign,当该属性指向一个已释放的对象时,您的应用程序会崩溃。

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

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

在正常情况下,您不想保留委托,因为它会导致保留周期。但在这种特殊情况下,这不是问题:UIApplication无论如何,当您的应用程序处于活动状态时,您的对象将一直存在。

于 2016-02-25T20:31:37.590 回答