执行 segue swift 4

Posted

技术标签:

【中文标题】执行 segue swift 4【英文标题】:perform 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 总是异步的? 是的。您需要在不进行任何网络访问的情况下在瞬间做出决定。 【参考方案1】:

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

因此:

    从按钮中移除 segue。

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

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

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

    当您完成验证逻辑时,您的登录操作应该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()
    
    

    注意,我对请求正文中的值进行百分比编码。尤其是密码,可能包含保留字符。而且我没有弄错使用.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
        ()
    
    
    

【讨论】:

以上是关于执行 segue swift 4的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 从地图注释中执行 Segue

Swift:执行 Segue 不触发 - 无错误(可达性)

Xcode Swift 使用警报执行 segue

使用标识符执行 segue 在 swift 2 中不起作用

Swift:如果条件不满足,则继续执行 segue

如何在swift3中完成5个文件下载请求后执行segue