【问题标题】:Bind RACComand to UIViewController event将 RACComand 绑定到 UIViewController 事件
【发布时间】:2015-10-03 14:53:08
【问题描述】:

我在我的项目中使用 MVVM 模式实现 RAC,现在我开始怀疑了。 我对服务器有很多调用,但它们都与 UIButton 相关联并在我的 ViewModel 中处理;现在我需要在加载 UIViewController 时调用服务器。在 MVVM 之前,我刚刚在 viewDidLoad 方法中创建了一个信号 voilá!,但我不确定是否可以将它放入 ViewController。 现在我不知道如何将 RACSignal 绑定到 ViewController 中的事件,最糟糕的是,我不确定这是否是遵循 MVVM 模式的方式。

当我通过用户操作(来自 UIButton)调用服务器时,我现在正在做的是:

视图控制器*

self.someButton.rac_command = viewModel.executeSomeAction
//On success:
self.viewModel.executeLoginCompleted.skip(1).subscribeNextAs {
  (isExecuting: Bool) -> () in
  //Do something
}
//On error:
self.viewModel.executeSomeActionError.subscribeNextAs {
  (error: NSError) -> () in
  //Dd something
}

视图模型*

var executeSomeAction: RACCommand?
var executeSomeActionError: RACSignal!
var executeLoginCompleted: RACSignal

executeSomeAction = RACCommand(enabled: combineValidationSignals) {
  (any:AnyObject!) -> RACSignal in
  println("ANY: \(any)")
  return self.executeLoginRequest()
}

executeSomeActionError = executeLogin!.errors
executeLoginCompleted = executeLogin!.executing

当 UIView 加载时,我应该如何创建 RACSignal 或 RACCommand?当然,遵循 MVVM 模式。

谢谢

【问题讨论】:

    标签: ios swift mvvm binding reactive-cocoa


    【解决方案1】:

    你有两个选择。一种比另一种更hacky,但更容易在您的应用程序中实现。

    选项 1:

    您可以为 UIViewController 编写一个扩展,该扩展使用关联对象将 viewDidLoadCommand: RACCommand 属性添加到 UIViewController。然后你调动 UIViewController 的 viewDidLoad() 方法,让它在 viewDidLoad() 上执行你的命令:

    extension UIViewController {
        private struct AssociatedKeys {
            static var ViewDidLoadCommand: String = "ViewDidLoadCommand"
        }
    
        var viewDidLoadCommand: RACCommand? {
            get {
                return objc_getAssociatedObject(self, &AssociatedKeys.ViewDidLoadCommand) as? RACCommand
            }
            set {
                if let newValue = newValue {
                    objc_setAssociatedObject(
                        self,
                        &AssociatedKeys.ViewDidLoadCommand,
                        newValue as RACCommand?,
                        UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                    )
                }
            }
        }
    
        func swizzled_viewDidLoad() {
            self.swizzled_viewDidLoad()
    
            self.viewDidLoadCommand?.execute(nil)
        }
    }
    
    // In the appDelegate
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
    
        method_exchangeImplementations(
            class_getInstanceMethod(UIViewController.self, "viewDidLoad"),
            class_getInstanceMethod(UIViewController.self, "swizzled_viewDidLoad"))
    
        return true
    }
    

    选项 2

    您可以只继承 UIViewController 并实现 viewDidLoadCommand 并在 viewDidLoad() 中调用它

    class ViewControllerSubClass : UIViewController {
        var viewDidLoadCommand: RACCommand?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.viewDidLoadCommand?.execute(nil)
        }
    }
    

    无论您选择哪种方法,您所要做的就是在您的自定义 viewControllers init 方法中设置命令,然后它将在 viewDidLoad 上执行。

    【讨论】:

      猜你喜欢
      • 2011-12-17
      • 1970-01-01
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-25
      • 2021-08-14
      相关资源
      最近更新 更多