How would I create a callback around an XML reques

2019-05-31 06:28发布

I've been trying to understand how callbacks work in Swift. I've gone over quite a few examples (like this one) that have helped me to better understand callbacks, but I haven't had any luck in properly implementing one.

I have a function that accepts a URL, downloads some XML data from a web api and then parses it into objects. At the same time I have a UILabel that is waiting for some data from the XML request.

Below is a partial example of my function that I'd like to set up with a callback. For the sake of clarity just assume it only returns a single data point which which will be assigned to a UILabel later:

XMLUtility.swift

// global
var weekForecasts = [DayForecast]()

class XMLUtility {

    func retrieveDataFromXML(myUrl: String) {

        if let url = NSURL(string: myUrl) {
            if let data = NSData(contentsOfURL: url) {
                var error: NSError?
                var cleanedData = filterData(data)

                if let doc = AEXMLDocument(xmlData: cleanedData, error: &error) {

                //... does some work parsing xml ////


                for day in date {

                   //... some work assigning values /////

                   weekForecasts.append(thisDay)

                }         
            }   
        }  
    } 

The problem occurs in my ViewController... I have some UILabels that are waiting for values from the XML data request. When the ViewController loads, the XML hasn't processed yet and the label failed to receive a value.

Here's a simplified example of what I am doing in my ViewController:

ViewController.swift

 @IBOutlet weak var currentTemperatureLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()



    currentTemperatureLabel.text = // I get a value out of my [DayForecasts]
}

I understand why this is the case, and I have a novice understanding of how to solve the problem. I believe I need to use a callback but, based on the examples I have seen so far, I am not sure how to implement one.

My question:

Given the example provided, how would I convert my retrieveDataFromXML method into a callback. Additionally, how do I call the function from my ViewController to access the data.

Any help on this would be greatly appreciated!

1条回答
迷人小祖宗
2楼-- · 2019-05-31 07:11
func retrieveDataFromXML(myUrl: String, completion: ((Array<DayForecast>) -> Void)) {

    if let url = NSURL(string: myUrl) {
        if let data = NSData(contentsOfURL: url) {
            var error: NSError?
            var cleanedData = filterData(data)
            var weekForecasts = [DayForecast]() //local variable

            if let doc = AEXMLDocument(xmlData: cleanedData, error: &error) {

                //... does some work creating objects from xml
                for day in date {

                   //... some work assigning values /////

                   weekForecasts.append(thisDay)

                }    
                //pass the local array into the completion block, which takes
                //Array<DayForecast> as its parameter
                completion(weekForecasts) 
            }
        }
    }  
}

called like

//in this example it is called in viewDidLoad
func viewDidLoad() {
    var urlString = "urlstring"
    retrieveDataFromXML(urlString, {(result) -> Void in
        //result is weekForecasts

        //UI elements can only be updated on the main thread, so get the main 
        //thread and update the UI element on that thread
        dispatch_async(dispatch_get_main_queue(), {
            self.currentTemperatureLabel.text = result[0] //or whatever index you want
            return
        })
    })
}

Is this what your question was asking for?

查看更多
登录 后发表回答