【问题标题】:perform segue swift 4执行 segue swift 4
【发布时间】:2018-05-18 05:40:07
【问题描述】:

我正在尝试使用我的数据库验证用户的登录。当按下登录按钮时,我想根据从数据库返回的信息来判断是否会发生转场。我从最初设置为 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
}

【问题讨论】:

  • 您不能执行异步操作来从shouldPerformSegue返回值。
  • 我试过 DispatchQueue.main.sync 还是不行
  • 没关系,数据任务还是异步的。
  • 抱歉,您能否进一步详细说明。你的意思是 URLSession.shared.dataTask 总是异步的?
  • 是的。您需要在不进行任何网络访问的情况下在瞬间做出决定。

标签: json swift post segue


【解决方案1】:

与其在点击按钮时启动 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
        }()
    
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-24
    • 2018-12-05
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多