将RACComand绑定到UIViewController事件

时间:2015-07-14 19:27:03

标签: ios swift mvvm binding reactive-cocoa

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

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

的ViewController *

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模式。

由于

1 个答案:

答案 0 :(得分:0)

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

选项1:

您可以编写UIViewController的扩展,该扩展使用associatedObjects向UIViewController添加viewDidLoadCommand: RACCommand属性。然后,您调用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上执行。