【问题标题】:How can I trigger async requests out of view controller如何触发视图控制器之外的异步请求
【发布时间】:2015-09-07 23:03:06
【问题描述】:

我正在构建一个 iOS 应用程序,我刚刚完成了我的登录/注册部分(请求一个sails.js rest Api) 目前我有 2 个带有重复代码的视图控制器,因为我在每个类的注册/登录按钮事件侦听器上发出了其余调用,并且我可以重构很多类似的代码。

我想做的是创建一个名为 ApiManager 的单例,它将包含我需要的所有调用。 (以及未来的)

问题在于,使用异步调用我无法创建一个函数 func login(username,password) 来返回数据,以便我可以存储它们并准备继续。

正确实现这一目标的简单/正确方法是什么?这意味着调用 ApiManager.myFunction 并在任何需要的地方使用结果(为数据填充表格视图,启动登录 segue 或注册成功)并使此函数可在另一个视图控制器中重用,即使它用于其他用途。我正在使用 swift。

编辑:这是我的做法,希望对您有所帮助

执行其余调用的函数:

func login(#username: String, password: String, resultCallback: (finalresult: UserModel!,finalerror:String!) -> Void) {
        Alamofire.request(.POST, AppConfiguration.ApiConfiguration.apiDomain+"/login", parameters: ["username": username,"password": password], encoding: .JSON)
            .responseJSON { request, response, data, error in

                if let anError = error
                {
                    resultCallback(finalresult: nil,finalerror:anError.localizedDescription)
                }else if(response!.statusCode == 200){
                    var user:UserModel = self.unserializeAuth(data!)//just processing the json using SwiftyJSON to get a easy to use object. 


                    resultCallback(finalresult: user,finalerror:nil)
                }else{
                    resultCallback(finalresult: nil,finalerror:"Username/Password incorrect!")
                }




            }.responseString{ (request, response, stringResponse, error) in

                // print response as string for debugging, testing, etc.



                println(stringResponse)

        }
    }

这就是我从 ViewController 调用此函数的方式:

@IBAction func onLoginTapped(sender: AnyObject) {//When my user tap the login button

        let username = loginInput.text;//taking the content of inputs
        let password = passwordInput.text;
        ApiManager.sharedInstance.login(username:username,password:password){
             [unowned self] finalresult,finalerror in
            if(finalresult !== nil){//if result is not null login is successful and we can now store the user in the singleton
                ApiManager.sharedInstance.current_user=finalresult
                self.performSegueWithIdentifier("showAfterLogin", sender: nil)//enter the actual app and leave the login process
            }else{
                self.displayAlert("Error!", message: finalerror)//it is basically launching a popup to the user telling him why it didnt work

            }
        }

    }

【问题讨论】:

    标签: swift ios8 sails.js alamofire swifty-json


    【解决方案1】:

    几乎我所有的应用程序都以Server 类结束,这是唯一知道如何与服务器通信的类。它进行调用,将结果解析为 Swift 结构并返回它。我的大多数服务器都返回 json,所以我使用 SwiftyJSON,但你可以为所欲为。

    关键是,因为这是唯一知道服务器通信的类,如果我需要更改用于进行通信的库(AFNetworking 1 vs 2 vs Parse,vs其他),这是我唯一的类需要触摸。

    class Server {
        static let instance = Server()
    
        func loginWithUsername(username: String, password: String, resultCallback: (result: Either<User, NSError>) -> Void) {
            // if login is successful call
            resultCallback(result: .Left(self.user!))
            // otherwise call
            resultCallback(result: .Right(error))
        }
    }
    

    使用示例:

    let server = Server.instance
    SVProgressHUD.showWithStatus("Loggin In...")
    server.loginWithUsername(username, password: password) { [unowned self] result in
        SVProgressHUD.dismiss()
        switch result {
        case .Left(let user):
            self.presentUserType(user.userType)
        case .Right(let error):
            self.warnUserWithMessage("An error occured. \(error.localizedDescription)")
        }
    }
    

    如果所有后续调用都需要用户名/密码,则服务器对象将维护它们的副本。如果登录返回一个令牌,则服务器会保留该令牌的副本。 QED。

    【讨论】:

    • 太棒了!我不知道 .Left .Right 它真的很有用。请告诉我代码第二部分中 [unowned self] 的用途是什么?
    • 我也收到了 Either 部分的错误,您是否使用了特定的框架?
    • 好的,我发现它来自 robrix/Either。如果不使用 Either,你将如何做同样的事情?
    • 我自己写了一个。但不管对你有用。谷歌“面向铁路的编程”以了解更多信息。如果没有 Either,您将不得不传入两个回调,或者有一个带有两个可选参数的回调,其中一个不变量将包含一个值。
    • 明白!感谢您的宝贵建议。
    【解决方案2】:

    我通常在我的视图控制器共享的基类中具有实用程序函数,并使用 NSNotificationCenter 对请求的结果做出反应。也可以通过委托(protocol & delegate.

    这主要是关于感知,但我发现更容易想象你可以在一个控制器上启动一个操作并在另一个控制器上做出反应,因为调用花费了这么长时间并且你没有阻止应用程序中的导航。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 2013-08-25
      • 2022-01-23
      相关资源
      最近更新 更多