2016-01-11 1 views
3

Я пытаюсь понять некоторые концепции ReactiveCocoa 4 и не нашел способ правильно проверить и отправить запрос на основе входов из формы входа ,
Мое текущее решение отправляет запросы по каждому действительному обновлению моих входов, что не очень хорошо.ReactiveCocoa 4, правильно отправить мой HTTP-запрос на основе события пользовательского интерфейса и проверки

Кажется, мне нужно использовать Actions и CocoaActions, чтобы исправить мою проблему, но я не понимаю, как правильно их реализовать.

Вот мой пример кода:
Я хочу, чтобы запрос на вход был отправлен при нажатии кнопки входа в систему, а поля ввода и пароля не пусты, иначе я просто покажу ошибку.
В настоящее время производитель остается в живых и продолжают посылать запросы, когда я изменить поля ввода, которые не очень хорошо ...

Я хотел бы пример того, как сделать это правильно :)

LoginViewModel.swift

class LoginViewModel { 
    let login = MutableProperty<String>("") 
    let password = MutableProperty<String>("") 

    init() { 

    } 

    func logIn() -> SignalProducer<Int, IntranetError> { 
     return SignalProducer { 
      observer, disposable in 
      combineLatest(self.login.producer, self.password.producer) 
      .promoteErrors(Moya.Error) 
      .filter { (credentials : (String, String)) in 

       guard credentials.0.length > 0 else { 
        observer.sendFailed(IntranetError.MissingLoginError) 
        return false 
       } 
       guard credentials.1.length > 0 else { 
        observer.sendFailed(IntranetError.MissingPasswordError) 
        return false 
       } 

       return true 
      } 
      .flatMap(.Latest) { (credentials : (String, String)) -> SignalProducer<User, Moya.Error> in 
       let login = credentials.0 
       let password = credentials.1 
       return IntranetProvider.request(Intranet.LogIn(login, password)).filterSuccessfulStatusCodes() 
        .mapObject(User) 
      } 
      .start { (event) -> Void in 
       switch event { 
       case .Next(let user): 
        UserManager.sharedManager.user = user; 
        print(user) 
        observer.sendCompleted() 
       case .Failed(let error): 
        observer.sendFailed(.MoyaError(error)) 
       default: 
        break 
       } 
      } 
     } 
    } 
} 

LoginViewController.swift

class LoginViewController: UIViewController, UITextFieldDelegate { 

    @IBOutlet weak var loginTextField: FramedTextField! 
    @IBOutlet weak var passwordTextField: FramedTextField! 
    @IBOutlet weak var connectButton: UIButton! 
    let viewModel : LoginViewModel = LoginViewModel() 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     viewModel.login <~ loginTextField.rac_text 
     viewModel.password <~ passwordTextField.rac_text 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    @IBAction func connectButtonTouched(sender: AnyObject) { 
     loginAsked() 
    } 

    func loginAsked() -> Void { 
     SVProgressHUD.showWithMaskType(.Black) 
     viewModel.logIn().throttle(0.5, onScheduler: QueueScheduler.mainQueueScheduler).start { (event) in 
      switch event { 
      case .Completed: 
       SVProgressHUD.dismiss() 
       self.connectionSuccessfull() 
      case .Failed(let error): 
       switch error { 
       case .MissingPasswordError : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Missing password", comment: "User password is missing")) 
       case .MissingLoginError : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Missing login", comment: "User login is missing")) 
       case .MoyaError(let error) : 
        SVProgressHUD.showErrorWithStatus(error.toString()) 
       default : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Internal error, please try again later", comment: "")) 
       } 
      default: 
       break 
      } 
     } 
    } 
} 

Благодаря

ответ

3

Наконец, после долгой работы, я нашел, как правильно его реализовать.
В конце концов, я немного переоценил процесс проверки, и теперь это намного проще.
Результат:

LoginViewModel.swift

class LoginViewModel { 

    let login = MutableProperty<String>("") 
    let password = MutableProperty<String>("") 

    var loginAction : Action<(String, String), User, IntranetError>! 
    var cocoaActionLogin : CocoaAction! 

    init() { 
     loginAction = Action { (let login, let password) in 
      return SignalProducer { 
       observer, disposable in 
       guard login.length > 0 else { 
        observer.sendFailed(IntranetError.MissingLoginError) 
        return 
       } 
       guard password.length > 0 else { 
        observer.sendFailed(IntranetError.MissingPasswordError) 
        return 
       } 
       print("SENT") 
       IntranetProvider.request(Intranet.LogIn(login, password)) 
       .filterSuccessfulStatusCodes() 
       .mapObject(User) 
       .start { (event) in 
        switch event { 
        case .Next(let user): 
         UserManager.sharedManager.user = user; 
         print(user) 
         observer.sendCompleted() 
        case .Failed(let error): 
         observer.sendFailed(.MoyaError(error)) 
        default: 
         observer.sendCompleted() 
        } 
       } 
      } 
     } 
     cocoaActionLogin = CocoaAction(loginAction) { _ in 
      return (self.login.value, self.password.value) 
     } 
    } 
} 

LoginViewController.swift

class LoginViewController: UIViewController, UITextFieldDelegate { 

    @IBOutlet weak var loginTextField: FramedTextField! 
    @IBOutlet weak var passwordTextField: FramedTextField! 
    @IBOutlet weak var connectButton: UIButton! 
    let viewModel : LoginViewModel = LoginViewModel() 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     viewModel.login <~ loginTextField.rac_text 
     viewModel.password <~ passwordTextField.rac_text 
     connectButton.addTarget(self.viewModel.cocoaActionLogin, action: CocoaAction.selector, forControlEvents: .TouchUpInside) 
     self.viewModel.loginAction.events 
      .observeOn(UIScheduler()) 
      .observeNext { (event) in 
      switch event { 
      case .Completed: 
       SVProgressHUD.dismiss() 
       self.connectionSuccessfull() 
      case .Failed(let error): 
       switch error { 
       case .MissingPasswordError : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Missing password", comment: "User password is missing")) 
       case .MissingLoginError : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Missing login", comment: "User login is missing")) 
       case .MoyaError(let error) : 
        SVProgressHUD.showErrorWithStatus(error.toString()) 
       default : 
        SVProgressHUD.showErrorWithStatus(NSLocalizedString("Internal error, please try again later", comment: "")) 
       } 
      default: 
       break 
      } 

     } 
    } 
} 
Смежные вопросы