首页 文章

将UIApplicationDelegate方法转换为RxSwift Observables

提问于
浏览
6

在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
}

当我启动我的应用程序"Active!"被打印,然后我在RxCocoa的 _RXDelegateProxy_ 类中遇到以下崩溃:

enter image description here

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

1 回答

  • 8

    对于RxSwift和内存管理来说,这似乎是一个非常棘手的问题 .

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

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

    问题是,当设置新的app代理时:

    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 对象将存在,直到您的应用程序仍处于活动状态 .

相关问题