首页 > 解决方案 > 执行 segue swift 4

问题描述

我正在尝试使用我的数据库验证用户的登录。当按下登录按钮时,我想根据从数据库返回的信息来判断是否会发生转场。我从最初设置为 true 的变量决策开始,如果我无法验证用户,我想将其设置为 false 并防止 segue。这是我拥有的代码,但它存在问题。最后的 return 语句总是正确的。基本上发生的事情是在从数据库返回响应之前首先调用 .resume() 之后最后的 return 语句。有人可以澄清为什么会这样吗

 override func shouldPerformSegue(withIdentifier identifier: String,sender: 
 Any?) -> Bool
 {
             var decision = true
            let url = URL(string:"http://192.23.25.98/login/php")
            var request = URLRequest(url: url!)
            request.httpMethod = "POST"
            let body = "UserNameLogIn=\(userName.text!.lowercased())&PasswordLogIn=\(passWord.text!.lowercased())"
            request.httpBody=body.data(using: String.Encoding.utf8)
            URLSession.shared.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in
                if (error == nil)
               {
                    DispatchQueue.main.async(execute: {
                        do
                        {
                            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? Dictionary<AnyHashable,AnyObject>
                            guard let parseJson = json else{
                                print ("error parsing")
                                return
                            }
                            let status = parseJson["status"]
                            if (status != nil)
                            {
                                if (parseJson.count>3)
                                {
                                    decision = true

                                }
                                else
                                {
                                    decision = false


                                }
                            }
                        }
                        catch
                        {

                            print("error: \(error)")
                        }
                    })
                }
                else
                {
                    decision = false
                }
                }.resume()
    return decision
}

标签: jsonswiftpostsegue

解决方案


与其在点击按钮时启动 segue 并尝试在 中捕获异步过程,不如shouldPerformSegue(withIdentifier:sender:)让按钮定义一个@IBAction执行验证请求并在成功时以编程方式启动 segue。

因此:

  1. 从按钮中删除 segue。

  2. control通过从第一个场景上方栏中的视图控制器图标拖动到第二个场景,在视图控制器之间添加 segue :

    在此处输入图像描述

  3. 选择 segue 并在属性检查器中为其命名:

    在此处输入图像描述

  4. 从按钮中删除 segue 后,您现在可以将按钮连接到@IBAction方法:

    在此处输入图像描述

  5. performSegue(withIdentifier:sender:)当您完成验证逻辑时,您的登录操作应该:

    performSegue(withIdentifier: "NextSceneSegue", sender: self)
    

    例如

    @IBAction func didTapLoginButton(_ sender: Any) {
        let url = URL(string:"http://192.23.25.98/login/php")
        var request = URLRequest(url: url!)
        request.httpMethod = "POST"
        request.httpBody = ["UserNameLogIn": useridTextField.text!, "PasswordLogIn": passwordTextField.text!]
            .map { $0.key + "=" + $0.value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)! }
            .joined(separator: "&")
            .data(using: .utf8)
    
        URLSession.shared.dataTask(with: request) { data, response, error in
            DispatchQueue.main.async {
                guard let data = data, let httpResponse = response as? HTTPURLResponse, (200 ..< 300) ~= httpResponse.statusCode, error == nil else {
                    // handle basic network errors here
                    return
                }
    
                guard let json = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] else {
                    // handle json parsing errors here
                    return
                }
    
                if json["status"] == nil  {
                    // handle missing status here
                    return
                }
    
                guard json.count > 3 else {
                    // handle incorrect count here
                    return
                }
    
                self.performSegue(withIdentifier: "NextSceneSegue", sender: self)
            }
        }.resume()
    }
    
  6. 请注意,我对请求正文中的值进行百分比编码。尤其是密码,可能包含保留字符。而且我没有犯使用的错误.urlQueryAllowed,而是使用.urlQueryValueAllowed了,其中我提取了一些保留字符:

    extension CharacterSet {
    
        /// Returns the character set for characters allowed in the individual parameters within a query URL component.
        ///
        /// The query component of a URL is the component immediately following a question mark (?).
        /// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query
        /// component is `key1=value1`. The individual parameters of that query would be the key `key1`
        /// and its associated value `value1`.
        ///
        /// According to RFC 3986, the set of unreserved characters includes
        ///
        /// `ALPHA / DIGIT / "-" / "." / "_" / "~"`
        ///
        /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters
        /// for the sake of compatibility with some erroneous implementations, so this routine also allows those
        /// to pass unescaped.
    
        static var urlQueryValueAllowed: CharacterSet = {
            let generalDelimitersToEncode = ":#[]@"    // does not include "?" or "/" due to RFC 3986 - Section 3.4
            let subDelimitersToEncode = "!$&'()*+,;="
    
            var allowed = CharacterSet.urlQueryAllowed
            allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
            return allowed
        }()
    
    }
    

推荐阅读