在 webservice 之后执行 segue

perform segue after webservice

嗨,我是 iOS 开发的新手,想知道 iOS 中是否有等效的 asynctask?我希望我的网络服务完成,然后我想将我的网络服务的内容传递给 nextview 控制器

@IBAction func searchAction(_ sender: Any) {

    let airportName: String = airportCode.text!
    let minutesBefore: String = minutesBehind.text!
    let minutesAfter: String = minutesAhead.text!

    //web service request

    self.data = FlightWebService().getFlightData(airportCode: airportName, minutesBehind: minutesBefore, minutesAhead: minutesAfter)
    print(self.data)


    //how to pass data to the next view controller
    performSegue(withIdentifier: "goToSearch", sender: self)
}

您可以使用 ios 7.0 及更高版本提供的 URLSession。

在您的方法中,您可以 运行 异步任务

func searchAction() {
    let defaultSessionConfiguration = URLSessionConfiguration.default
    let defaultSession = URLSession(configuration: defaultSessionConfiguration)

    let url = URL(string: "typeHereYourURL")
    var urlRequest = URLRequest(url: url!)

    let params = ""// json or something else
    let data = params.data(using: .utf8)

    urlRequest.httpMethod = "POST"
    urlRequest.httpBody = data

    let dataTask = defaultSession.dataTask(with: urlRequest) { (data, response, error) in
        performSegue(withIdentifier: "YourVCIdentifier", sender: self)
    }

    dataTask.resume()
}

或者您可以在另一个线程中创建串行队列和 运行 FlightWebService 请求

func searchAction() {
    let newQueue = DispatchQueue(label: "queue_label")
    newQueue.async {
        self.data = FlightWebService().getFlightData(airportCode: airportName, minutesBehind: minutesBefore, minutesAhead: minutesAfter)
        print(self.data)

        DispatchQueue.main.async {
            performSegue(withIdentifier: "YourVCIdentifier", sender: self)
        }
    }
}

并覆盖它以将参数发送到下一个 ViewController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "YourVCIdentifier" {
        if let destinationVC = segue.destination as? YourVC {
            destinationVC.exampleStringProperty = //send data here recived earlier
        }
    }
}

根据@SH_Khan 的要求,我已将您的 URLRequest 呼叫放在 FlightWebService class 中。这应该可以解决问题。

class FlightWebService {

    // Change the method's signature to accept a completion block
    static func getFlightData(airportCode: String, minutesBehind: String, minutesAhead: String, completion: (Data?, Response?, Error?) -> Void) {
        let defaultSessionConfiguration = URLSessionConfiguration.default
        let defaultSession = URLSession(configuration: defaultSessionConfiguration)

        let url = URL(string: "typeHereYourURL")
        var urlRequest = URLRequest(url: url!)

        let params = ""// json or something else
        let data = params.data(using: .utf8)

        urlRequest.httpMethod = "POST"
        urlRequest.httpBody = data

        // Launch the task **IN BACKGROUND** with the provided completion handler block
        DispatchQueue.global(qos: .background).async {
            let dataTask = defaultSession.dataTask(with: urlRequest, completionHandler: completion) 
            dataTask.resume()
        }
    }
}

@IBAction func searchAction(_ sender: Any) {

    let airportName: String = airportCode.text!
    let minutesBefore: String = minutesBehind.text!
    let minutesAfter: String = minutesAhead.text!

    //web service request
    FlightWebService().getFlightData(airportCode: airportName, minutesBehind: minutesBefore, minutesAhead: minutesAfter) { (data, response, error) in
        self.data = data
        print(self.data)
        // Always perform view-related stuff on the main thread
        DispatchQueue.main.async {
            performSegue(withIdentifier: "goToSearch", sender: self)
        }
    }
}

您的 FlightService 函数需要执行异步任务并使用 completionHandlers 将响应传递回调用代码。

看下面的代码

// model
class Flight {}

// flight service
class FlightService: NSObject
{
    func getFlightData(airportCode: String, minutesBehind: Int, minutesAhead: Int, completion: @escaping (Bool, [Flight]?) -> Void) {
        // main thread still
        let url = NSURL(string: "http://..........")!
        let request = NSMutableURLRequest(url: url as URL)
        request.httpMethod = "Get"

        // This always runs in the background, so no need to specifically put it there
        let task = URLSession.shared.dataTask(with: request as URLRequest){ data,response,error in
            guard error == nil else {
                completion(false, nil)
                return
            }

            // parse response data instead I'll create blank array
            var parsedFlights = [Flight]()
            completion(true, parsedFlights)
        }

        task.resume()
    }
}

// USAGE

@IBAction func searchAction(_ sender: Any) {

    let airportName: String = "airportCode.text!"
    let minutesBefore: String = "minutesBehind.text!"
    let minutesAfter: String = "minutesAhead.text!"

    FlightWebService().getFlightData(airportCode: airportName, minutesBehind: minutesBefore, minutesAhead: minutesAfter) { [weak self] success, flights in
        // we are still in a background thread here and would need to Dispatch to the main thread to update any UI
        guard let strongSelf = self, success else { return }

        print(flights.count)
        strongSelf.flightSearchResults = flights
        strongSelf.performSegue(withIdentifier: "goToSearch", sender: self)
    }
}

NSURLSession 始终在后台线程中运行,因此无需手动分派。

在 searchFunction 一旦 completionHandler returns 此时我们仍然 运行 在后台线程中但是我们已经解析了我们的响应数据并传回了航班数据,如果我们需要更新any UI 从这里我们需要分派到主线程。

注意: 你通常还应该在闭包中使用 weak self 因为在异步任务期间,我们可能会丢失对调用 [=25= 的引用](自己)。