【问题标题】:How would I create a callback around an XML request?如何围绕 XML 请求创建回调?
【发布时间】:2015-07-04 11:35:36
【问题描述】:

我一直试图了解回调在 Swift 中是如何工作的。我已经阅读了很多示例 (like this one),这些示例帮助我更好地理解了回调,但我没有任何运气来正确实施。

我有一个接受 URL 的函数,从 Web api 下载一些 XML 数据,然后将其解析为对象。同时我有一个 UILabel 正在等待来自 XML 请求的一些数据。

下面是我想设置回调的函数的部分示例。为了清楚起见,假设它只返回一个数据点,稍后将分配给 UILabel

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)

                }         
            }   
        }  
    } 

问题出现在我的 ViewController... 我有一些 UILabel 正在等待来自 XML 数据请求的值。当 ViewController 加载时,XML 尚未处理,标签无法接收值。

这是我在 ViewController 中所做的简化示例:

ViewController.swift

 @IBOutlet weak var currentTemperatureLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()



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

我明白为什么会这样,而且我对如何解决问题有一个新手的理解。我相信我需要使用回调,但是根据我目前看到的示例,我不确定如何实现。

我的问题:

鉴于提供的示例,我如何将我的 retrieveDataFromXML 方法转换为回调。另外,如何从 ViewController 调用函数来访问数据。

对此的任何帮助将不胜感激!

【问题讨论】:

  • 我想出了一个使用全局变量的临时解决方案,但我真的很想更好地理解闭包和回调。
  • 你看过NSURLSession吗?它是一个 Cocoa 类,它从 URL 请求数据,并允许您提供一个完成处理程序来处理从 URL 检索到的数据。这可能比尝试自己重新发明回调功能更好。你可能想看的方法是dataTaskWithURL:completionHandler: 这里有一个链接:developer.apple.com/library/ios/documentation/Foundation/…:
  • 如果以后有时间,我可以提供一个编码示例,但我认为我至少建议您朝那个方向看。
  • 罗曼,我看过了。老实说,在我看到生产代码示例之前,我永远不明白如何应用我在苹果文档中读到的内容。我已经解决了导致我发布这个问题的原始问题,但我创造了一个赏金,因为我想对回调的工作原理有一个更基本的了解。我真的很感激一个编码的例子!
  • 附带说明,我知道我确实需要培养从苹果文档中学习的技能。正在努力

标签: ios swift xml-parsing callback


【解决方案1】:
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) 
            }
        }
    }  
}

像这样称呼

//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
        })
    })
}

这是你的问题吗?

【讨论】:

  • 感谢您抽出宝贵时间回答,今晚我会试一试,看看它是如何工作的。
  • Np,您可能需要更改的唯一内容是您传入完成的数据类型,我不知道“从 xml 创建对象的一些工作”做了什么,但您可以更改完成块接受的内容与您创建的内容相匹配。如果你想传入多个东西,它甚至可以有多个参数。
  • 我应该将什么传递给完成处理程序?此方法接受一个 url,请求并获取 XML 数据并对其进行解析。为了使该方法起作用,我唯一需要传入的是一个 url。
  • 我猜 labelOne 是一个 ViewController IBOutlet;如果是这种情况,那么由于labelOne 在闭包内使用,您需要明确引用self,因此您需要调用self.labelOne.text = ...。此外,如果 ViewController 拥有 XMLUtility(即 retrieveDataFromXML 不是类方法),您将创建一个引用循环,因此您可能希望 self 在闭包内成为 unowned。另请注意,如果retrieveDataFromXML不在主队列中,则无法直接修改UI,但需要回调主队列
  • @DanBeaulieu 您将解析的 XML 传递给完成处理程序。完成处理程序是一个闭包(代码块),当您调用完成(参数)时运行,它在 xml 被解析后调用。参数是您在解析 xml 后执行您希望完成的操作所需的任何参数。在您的情况下,您希望使用 xml 中的某些内容更新标签文本,因此完成处理程序需要具有 xml。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
相关资源
最近更新 更多