在Rx
Swift / RxCocoa中,您可以为委托创建一个反应式包装器(例如UIScrollViewDelegate或CLLocationManagerDelegate),以便为某些委托方法启用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这样的东西?
解决方法
对于RxSwift和内存管理来说,这似乎是一个非常棘手的问题.
DelegateProxyType的默认实现将委托代理的实例(在本例中为RxUIApplicationDelegateProxy)设置为UIApplication的委托.
它还将原始AppDelegate存储为名为forwardToDelegate的属性,因此仍可以将所有委托方法传递给它.
问题是,当设置新的app代理时:
application.delegate = delegate as? UIApplicationDelegate
原来的一个被解除分配!你可以通过覆盖AppDelegate中的deinit来检查它.原因在@L_404_2@中解释.由于属性forwardToDelegate属于assign类型,因此当应用程序指向已解除分配的对象时,应用程序会崩溃.
我找到了解决方法.我不确定它是否是推荐的方式,所以请注意.您可以在RxUIApplicationDelegateProxy中覆盖DelegateProxyType中的方法:
override func setForwardToDelegate(delegate: AnyObject?,retainDelegate: Bool) { super.setForwardToDelegate(delegate,retainDelegate: true) }
在正常情况下,您不希望保留委托,因为它会导致保留周期.但在这种特殊情况下,这不是问题 – 您的UIApplication对象将存在,直到您的应用程序仍处于活动状态.