Swift函数在完成处理之前返回值[重复]

时间:2023-01-23 18:20:50

This question already has an answer here:

这个问题在这里已有答案:

Basically I have a code for posting simple data to a server and will return a boolean value success if the post request was successful but it seems to be that the boolean value is returned before even the data is processed, am I doing something wrong?

基本上我有一个代码,用于将简单数据发布到服务器,如果post请求成功,将返回布尔值成功,但似乎是在处理数据之前返回布尔值,我做错了什么?

public func postRequest(rawText: String) -> Bool {
    var success = true
    let destUrl = "http://api.getquesto.com:8080/upload/"
    var request = URLRequest(url: URL(string: destUrl)!)
    request.httpMethod = "POST"
    let postString = rawText
    request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
//    request.setValue("compute", forHTTPHeaderField: "Questo-Query")
//    request.setValue("Fuck you", forHTTPHeaderField: "quizTitle")

    request.httpBody = postString.data(using: .utf8)
    print(request.httpBody!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(error)")
            success = false
            print(success)

            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }

        let responseString = String(data: data, encoding: .utf8)
        do {
            if let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: UInt(0))) as? [String: Any] {
                print("json \(json)")
            } else {
                print("can not cast data")
                success = false

            }
        } catch let error {
            print("cant parse json \(error)")
            success = false
            print(success)

        }

        print("responseString = \(responseString)")
        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
        //print(dataString)
        //print("responseString = \(responseString)")
        constantVariables.rawQuestionData = dataString as! String
        let processedResults = dataString?.replacingOccurrences(of: "\\n", with: " ")
        print("processed results = " + (processedResults! as String))
        let newArray = processedResults!.components(separatedBy: ", \"")
        //print(newArray)

        for index in 0...(newArray.count - 1) {
            if index%2 == 0 {
                constantVariables.questions.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: index/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                //        print("question array: " + ConstantsArray.answerArray[index/2])
            }else{
                constantVariables.answers.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: (index-1)/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                print("answer array: " + constantVariables.answers[(index-1)/2])

            }
        }
    }
    task.resume()
    print(success)
    return success
    }

1 个解决方案

#1


2  

This is happening because the function directly returns the value of success, dataTask works asynchronously, so, the function should NOT wait until dataTask finishes the parsing to edit the value of success, i.e: return success is executed before dataTask edits the value of success.

发生这种情况是因为函数直接返回成功的值,dataTask异步工作,因此,函数不应等到dataTask完成解析才能编辑成功的值,即:在dataTask编辑成功值之前执行返回成功。

I suggest to let the function handles a completion closure instead of direct returning of Bool.

我建议让函数处理完成闭包而不是直接返回Bool。

Your function should be similar to:

你的功能应该类似于:

public func postRequest(rawText: String, completion: @escaping (_ success: Bool) -> ()) {
    var success = true
    let destUrl = "http://api.getquesto.com:8080/upload/"
    var request = URLRequest(url: URL(string: destUrl)!)
    request.httpMethod = "POST"
    let postString = rawText
    request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
    //    request.setValue("compute", forHTTPHeaderField: "Questo-Query")
    //    request.setValue("Fuck you", forHTTPHeaderField: "quizTitle")

    request.httpBody = postString.data(using: .utf8)
    print(request.httpBody!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(error)")
            success = false
            print(success)

            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }

        let responseString = String(data: data, encoding: .utf8)
        do {
            if let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: UInt(0))) as? [String: Any] {
                print("json \(json)")
            } else {
                print("can not cast data")
                success = false

            }
        } catch let error {
            print("cant parse json \(error)")
            success = false
            print(success)

        }

        print("responseString = \(responseString)")
        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
        //print(dataString)
        //print("responseString = \(responseString)")
        constantVariables.rawQuestionData = dataString as! String
        let processedResults = dataString?.replacingOccurrences(of: "\\n", with: " ")
        print("processed results = " + (processedResults! as String))
        let newArray = processedResults!.components(separatedBy: ", \"")
        //print(newArray)

        for index in 0...(newArray.count - 1) {
            if index%2 == 0 {
                constantVariables.questions.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: index/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                //        print("question array: " + ConstantsArray.answerArray[index/2])
            }else{
                constantVariables.answers.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: (index-1)/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                print("answer array: " + constantVariables.answers[(index-1)/2])

            }
        }

        completion(success)
    }
    task.resume()
    print(success)
}

In Swift 3, you should use @escaping, for more information, you might want to check this answer.

在Swift 3中,您应该使用@escaping,有关更多信息,您可能需要检查此答案。

Calling:

呼叫:

postRequest(rawText: "rawText", completion: { success in
    print(success)
})

Now, it should wait untill dataTask finish it's parsing, and then, the code in the completion will be called.

现在,它应该等待,直到dataTask完成它的解析,然后,将调用完成中的代码。

Hope it helped.

希望它有所帮助。

#1


2  

This is happening because the function directly returns the value of success, dataTask works asynchronously, so, the function should NOT wait until dataTask finishes the parsing to edit the value of success, i.e: return success is executed before dataTask edits the value of success.

发生这种情况是因为函数直接返回成功的值,dataTask异步工作,因此,函数不应等到dataTask完成解析才能编辑成功的值,即:在dataTask编辑成功值之前执行返回成功。

I suggest to let the function handles a completion closure instead of direct returning of Bool.

我建议让函数处理完成闭包而不是直接返回Bool。

Your function should be similar to:

你的功能应该类似于:

public func postRequest(rawText: String, completion: @escaping (_ success: Bool) -> ()) {
    var success = true
    let destUrl = "http://api.getquesto.com:8080/upload/"
    var request = URLRequest(url: URL(string: destUrl)!)
    request.httpMethod = "POST"
    let postString = rawText
    request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
    //    request.setValue("compute", forHTTPHeaderField: "Questo-Query")
    //    request.setValue("Fuck you", forHTTPHeaderField: "quizTitle")

    request.httpBody = postString.data(using: .utf8)
    print(request.httpBody!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(error)")
            success = false
            print(success)

            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }

        let responseString = String(data: data, encoding: .utf8)
        do {
            if let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions(rawValue: UInt(0))) as? [String: Any] {
                print("json \(json)")
            } else {
                print("can not cast data")
                success = false

            }
        } catch let error {
            print("cant parse json \(error)")
            success = false
            print(success)

        }

        print("responseString = \(responseString)")
        let dataString = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
        //print(dataString)
        //print("responseString = \(responseString)")
        constantVariables.rawQuestionData = dataString as! String
        let processedResults = dataString?.replacingOccurrences(of: "\\n", with: " ")
        print("processed results = " + (processedResults! as String))
        let newArray = processedResults!.components(separatedBy: ", \"")
        //print(newArray)

        for index in 0...(newArray.count - 1) {
            if index%2 == 0 {
                constantVariables.questions.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: index/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                //        print("question array: " + ConstantsArray.answerArray[index/2])
            }else{
                constantVariables.answers.insert(newArray[index].replacingOccurrences(of: "\"", with: "").replacingOccurrences(of: "]", with: "").replacingOccurrences(of: "[", with: ""), at: (index-1)/2)

                //        ConstantsArray.questionArray.append(newArray[index])
                print("answer array: " + constantVariables.answers[(index-1)/2])

            }
        }

        completion(success)
    }
    task.resume()
    print(success)
}

In Swift 3, you should use @escaping, for more information, you might want to check this answer.

在Swift 3中,您应该使用@escaping,有关更多信息,您可能需要检查此答案。

Calling:

呼叫:

postRequest(rawText: "rawText", completion: { success in
    print(success)
})

Now, it should wait untill dataTask finish it's parsing, and then, the code in the completion will be called.

现在,它应该等待,直到dataTask完成它的解析,然后,将调用完成中的代码。

Hope it helped.

希望它有所帮助。