【问题标题】:Swift URL Response is nilSwift URL 响应为零
【发布时间】:2015-03-05 02:20:49
【问题描述】:

我创建了一个自定义 DataManager 类。在其中,我想在一个方法中获取数据并返回一个 NSData 对象,然后再转换为 JSON。

我尝试使用 completionHandler 获取数据,但没有成功:

class func fetchData() -> NSData? {
    var session = NSURLSession.sharedSession(),
        result = NSData?()
    let DataURL : NSURL = NSURL(string: "http://...file.json")!

    let sessionTask = session.dataTaskWithURL(DataURL, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
        result = data
    })
    sessionTask.resume()
    return result
}

【问题讨论】:

    标签: session swift return nsurl null


    【解决方案1】:

    dataTask 异步运行。这意味着当您从fetchData 返回时,将不会调用完成处理程序闭包。因此,result 尚未设置。

    因此,您不应尝试从异步方法同步检索数据。相反,您应该自己使用异步完成处理程序模式:

    class func fetchData(completion: @escaping (Data?, Error?) -> Void) {
        let session = URLSession.shared
        let url = URL(string: "http://...file.json")!
    
        let task = session.dataTask(with: url) { data, response, error in
            completion(data, error)
        }
        task.resume()
    }
    

    你会这样称呼它:

    MyClass.fetchData { data, error in
        guard let data = data, error == nil else {
            print(error ?? "Unknown error")
            return
        }
    
        // use `data` here; remember to dispatch UI and model updates to the main queue
    }
    
    // but do not try to use `data` here
    
    ...
    

    仅供参考,有关 Swift 3 之前的原始语法,请参阅 previous revision of this answer

    【讨论】:

    • 非常感谢您的回复。不过我还是有问题。这些异步方法似乎具有低优先级 AKA,它们最后运行。我正在使用表格视图,我需要在主要加载函数(例如设置行数的函数)之前填充一个对象数组。如何强制这些异步函数在这些之前运行?
    • 您通常不会尝试让 tableview 等待网络请求,而是让它去发现numberOfRowsInSection 为零并得出结论,没有任何东西(还)要呈现。然后,在 fetchData 完成处理程序(在网络请求完成后调用)内,填充模型对象,然后告诉 tableview 重新加载自己(例如self.tableView.reloadData())。
    猜你喜欢
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    相关资源
    最近更新 更多