waddup dude!

1a- You're headed in the right direction. You put loginButtonPressed in the view controller and that is exactly where it should be. Event handlers for controls should always go into the view controller - so that is correct.

1b - in your view model you have comments stating, "show the user an alert with the error". You don't want to display that error from within the validate function. Instead create an enum that has an associated value (where the value is the error message you want to display to the user). Change your validate method so that it returns that enum. Then within your view controller you can evaluate that return value and from there you will display the alert dialog. Remember you only want to use UIKit related classes only within the view controller - never from the view model. View model should only contain business logic.

enum StatusCodes : Equatable { case PassedValidation case FailedValidation(String) func getFailedMessage() -> String { switch self { case StatusCodes.FailedValidation(let msg): return msg case StatusCodes.OperationFailed(let msg): return msg default: return "" } } } func ==(lhs : StatusCodes, rhs : StatusCodes) -> Bool { switch (lhs, rhs) { case (.PassedValidation, .PassedValidation): return true case (.FailedValidation, .FailedValidation): return true default: return false } } func !=(lhs : StatusCodes, rhs : StatusCodes) -> Bool { return !(lhs == rhs) } func validate(username : String, password : String) -> StatusCodes { if username.isEmpty || password.isEmpty { return StatusCodes.FailedValidation("Username and password are required") } return StatusCodes.PassedValidation }

2 - this is a matter of preference and ultimately determined by the requirements for your app. In my app I pass these values in via the login() method i.e. login(username, password).

3 - Create a protocol named LoginEventsDelegate and then have a method within it as such:

func loginViewModel_LoginCallFinished(successful : Bool, errMsg : String)

However this method should only be used to notify the view controller of the actual results of attempting to login on the remote server. It should have nothing to do with the validation portion. Your validation routine will be handled as discussed above in #1. Have your view controller implement the LoginEventsDelegate. And create a public property on your view model i.e.

class LoginViewModel { var delegate : LoginEventsDelegate? }

Then in the completion block for your api call you can notify the view controller via the delegate i.e.

func login() { // Call the login() method in ApiHandler let api = ApiHandler() let successBlock = { [weak self](data) -> Void in if let this = self { this.delegate?.loginViewModel_LoginCallFinished(true, "") } } let errorBlock = { [weak self] (error) -> Void in if let this = self { var errMsg = (error != nil) ? error.description : "" this.delegate?.loginViewModel_LoginCallFinished(error == nil, errMsg) } } api.login(username!, password: password!, success: successBlock, error: errorBlock) }

and your view controller would look like this:

class loginViewController : LoginEventsDelegate { func viewDidLoad() { viewModel.delegate = self } func loginViewModel_LoginCallFinished(successful : Bool, errMsg : String) { if successful { //segue to another view controller here } else { MsgBox(errMsg) } } }

Some would say you can just pass in a closure to the login method and skip the protocol altogether. There are a few reasons why I think that is a bad idea.

Passing a closure from the UI Layer (UIL) to the Business Logic Layer (BLL) would break Separation of Concerns (SOC). The Login() method resides in BLL so essentially you would be saying "hey BLL execute this UIL logic for me". That's an SOC no no!

BLL should only communicate with the UIL via delegate notifications. That way BLL is essentially saying, "Hey UIL, I'm finished executing my logic and here's some data arguments that you can use to manipulate the UI controls as you need to".

So UIL should never ask BLL to execute UI control logic for him. Should only ask BLL to notify him.

4 - I've seen ReactiveCocoa and heard good things about it but have never used it. So can't speak to it from personal experience. I would see how using simple delegate notification (as described in #3) works for you in your scenario. If it meets the need then great, if you're looking for something a bit more complex then maybe look into ReactiveCocoa.

Btw, this also is technically not an MVVM approach since binding and commands are not being used but that's just "ta-may-toe" | "ta-mah-toe" nitpicking IMHO. SOC principles are all the same regardless of which MV* approach you use.