如何将字符串数据从API POST请求传递到另一个ViewController

问题描述

我绝对是Swift和编程的初学者。

我不知道如何从调用POST请求的函数传递响应到第二个视图控制器上的文本标签。我认为主线程可能出了点问题,但我不知道如何解决。我确实尝试搜索解决方案,但对我没有任何帮助。

这是我的功能:

 func getBookTitle() -> String {
        
        var bookTitle = ""
            
        
        if let bookNameURL = URL(string: urlString) {
            
            
            do {
                let htmlString = try String(contentsOf: bookNameURL,encoding: .utf8)
                let htmlContent = htmlString
                
                do {
                    let doc = try SwiftSoup.parse(htmlContent)
                    
                    do {
                        let bookNumber = try doc.select("a.dlink").attr("onclick")
                        let bookNumberTrim = bookNumber.trimmingCharacters(in: CharacterSet.decimalDigits.inverted).components(separatedBy: ",")
                        
                        do {
                            
                            let bookid = bookNumberTrim[0]
                            let passageid = bookNumberTrim[1]
                            
                            
                            print(bookid)
                            print(passageid)
                            
                            
                            
                            //Get Book Title
                            
                            let url:URL = URL(string: "\(urlString)/getname")!
                            let session = URLSession.shared
                            
                            let request = NSMutableURLRequest(url: url)
                            request.httpMethod = "POST"
                            request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
                            
                            let paramString = "bookid=\(bookid)&passageid=\(passageid)"
                            
                            request.httpBody = paramString.data(using: String.Encoding.utf8)
                            
                            

                            let task = session.dataTask(with: request as URLRequest) { (data,response,error) in
                                
                                
                                guard let data = data,let _:URLResponse = response,error == nil else {
                                    print("error")
                                    return
                                }
                                
                                let dataString = String(data: data,encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
                                
                                
                                do {
                                    
                                    let doc: Document = try SwiftSoup.parse(dataString ?? "")
                                    
                                    do {
                                        
                                        let bTitle = try doc.select("div").first()
                                        bookTitle = try bTitle!.text()
                                        
                                        print(bookTitle)
                                        
                                    }
                                } catch {
                                    print(error)
                                }
                                
                            }
                            task.resume()
                            
                            
                        }
                        
                    } catch {
                        print(error)
                        
                    }
                }
                
            } catch let error {
                print("Error \(error)")
            }
            
            
        } else {
            print("Something wrong")
        }
        
        return bookTitle
        
    }

这就是我试图将数据传递到另一个VC的方式:

@IBAction func infoButtonPressed(_ sender: UIButton) {
    
    performSegue(withIdentifier: "goToInfo",sender: sender)
}



override func prepare(for segue: UIStoryboardSegue,sender: Any?) {
    
    if segue.identifier == "goToInfo" {
        let destinationVC = segue.destination as! BookInfoVC
        
        destinationVC.bookName = networkService.getBookTitle()

    }
    
}

第二个VC:

class BookInfoVC: UIViewController {
    
    
    @IBOutlet weak var bookTitle: UILabel!
    
    var bookName: String!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        bookTitle.text = bookName
        
    }
    
}

该函数的响应是一个字符串行。

非常感谢!


UPD: 我尝试在函数中实现完成处理程序,现在看起来像这样:

func getBookTitle(completion: @escaping (String) -> ()) {
        
        if let bookNameURL = URL(string: urlString) {
            
            do {
                let htmlString = try String(contentsOf: bookNameURL,encoding: .utf8)
                let htmlContent = htmlString
                
                do {
                    let doc = try SwiftSoup.parse(htmlContent)
                    
                    
                    do {
                        let bookNumber = try doc.select("a.dlink").attr("onclick")
                        let bookNumberTrim = bookNumber.trimmingCharacters(in: CharacterSet.decimalDigits.inverted).components(separatedBy: ",")
                        
                        
                        do {
                            let bookid = bookNumberTrim[0]
                            let passageid = bookNumberTrim[1]
                        
                            
                            
                            //MARK: - Fetch book title
                            
                            let params = BookTitle(bookid: bookid,passageid: passageid)
                            
                            
                            AF.request("\(self.urlString)/getname",method: .post,parameters: params).validate(contentType: ["application/x-www-form-urlencoded"]).response { (response) in
                                
                                
                                
                                if let data = response.data,let utf8Text = String(data: data,encoding: .utf8) {
                                    
                                    
                                    do {
                                        let html: String = utf8Text
                                        let doc: Document = try SwiftSoup.parse(html)

                                        do {

                                            let parseTitle = try doc.select("div").first()
                                            let bookTitle = try parseTitle!.text()
                                            completion(bookTitle)

                                        } catch {
                                            print(error)
                                        }
                                        
                                        
                                    } catch {
                                        print(error)
                                    }
  
                                }
                            
                            }
                        }
                        
                    } catch {
                        print(error)
                    }
                    
                }
                
            } catch let error {
                print("Error \(error)")
            }
                        
            
        } else {
            print("Something wrong")
        }
        
    }

我称之为:

@IBAction func infoButtonPressed(_ sender: UIButton) {
    
    self.performSegue(withIdentifier: "goToInfo",sender: self)
}


override func prepare(for segue: UIStoryboardSegue,sender: Any?) {
    

    if segue.identifier == "goToInfo" {
        let destinationVC = segue.destination as! BookInfoVC
        
        
        networkService.getBookTitle { bookTitle in
            destinationVC.bookName = bookTitle
            print(bookTitle)

        }

    }

我尝试将DispatchQueue.main.async粘贴到各处,但是它仍然没有更新第二个VC上的文本标签。但是在主视图控制器中,它工作正常。

解决方法

简短的回答:您不能。您正在发出异步请求。该函数将在结果可用之前返回。您需要重写函数以使用完成处理程序。然后,当结果可用时,您将调用完成处理程序。在此板上对此进行了广泛的讨论。

编辑:

您更新后的getBookTitle(completion:)函数看起来不错,但是现在您遇到了排序问题。

您的第一个视图控制器中的prepare(for segue:)方法使用您的networkService.getBookTitle(completion:)函数,并在完成处理程序中设置destinationVC.bookName

但是,请记住networkService.getBookTitle(completion:)是异步运行的。它立即返回,等待网络结果,然后然后调用完成处理程序。

您的目标视图控制器(类型为BookInfoVC)尝试通过其bookName方法将viewDidLoad安装到其UI中。在第一个视图控制器的viewDidLoad()触发之后,prepare(for segue:)被立即调用。在调用viewDidLoad时,bookName很可能仍然为零。

您需要在BookInfoVC的{​​{1}}属性上添加didSet方法,以使其响应书名的更改。可能看起来像这样:

bookName

如果您这样做,则在getBookTitle()的完成处理程序触发时,它将更改var bookName: String! { didSet: { bookTitle.text = bookName } } 。这将触发destinationVC.bookName的{​​{1}} BookInfoVC代码,并将更新后的bookName安装到UI中。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...