我一直在为watchos 2开发一个应用程序,结果发现我的函数使用NSData(contentsOfUrl)
下载一些json数据,可能太重,导致应用程序崩溃。我的研究让我相信NSURLSession
是一条路要走,但是我很难弄清楚如何转换我的函数,使结果以同样的方式返回。
在我的应用程序中,我有一行let data = myData()
。这就叫mydata.swift;
class myData {
var datas = myData.fetchData()
class func fetchData() -> [myData] {
let myURL = "http://www.url.com/json/"
let dataURL = NSURL(string: myURL)
var optData:NSData? = nil
do {
optData = try NSData(contentsOfURL: dataURL!, options: NSDataReadingOptions.DataReadingMappedIfSafe)
}
catch {
print("Handle \(error) here.")
}
var datas = [myData]()
if let data = optData {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for item in json {
//Do JSON stuff and
//Append to datas array
datas.append(dataSet)
}
} catch {
print(error)
}
}
return datas
}
}
}
此代码已被稍微截断,但在模拟器中运行时没有问题。但是,在设备上,当调用此代码时,它会崩溃。
这是我将mydata.swift转换为nsurlsession的尝试;
class myData {
class func fetchData() -> [myData] {
var task: NSURLSessionDataTask?
let myURL = "http://www.url.com/json/"
let dataURL = NSURL(string: myURL)
let conf = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: conf)
task = session.dataTaskWithURL(dataURL!) { (data, res, error) in
if let e = error {
print("dataTaskWithURL fail: \(e.debugDescription)")
return
}
var datas = [myData]()
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for item in json {
//Do JSON stuff
//Append to datas array
datas.append(dataSet)
}
} catch {
print(error)
}
return datas
//Unexpected return value in non-void function
}
}
}
有没有可能有人建议我如何成功地消除错误,以及我如何仍然能够调用
let data = myData()
并让它以NSData(contentsofUrl)
相同的方式返回。我确实理解nsurlsession将需要一个完成处理程序或其他东西,因为它运行在同一个线程上,但我无法理解它!谢谢! 最佳答案
恐怕你不能照你说的做。在传输整个文件之前,contentsOfURL
方法不会返回。如果连接速度慢或文件很大,则由于主线程正忙,ui将冻结。只对本地文件使用该方法。
看来你的第二次尝试有两个问题:
首先,出于安全原因,默认情况下只能加载安全(https:)url。请参阅此注释:https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/
其次,dataTaskWithURL
不会启动传输;在您指示datatask通过调用task.resume()
启动之前,它不会执行任何操作。传输完所有数据后,闭包代码将由另一个线程执行。这就是为什么不能返回值。
您仍然可以创建数据数组,但需要将声明移到类的顶层。记住闭包是由不同的线程执行的,所以您需要从闭包中引用数组作为self.datas
。
如果需要在闭包中加载数据后更新ui元素,则需要通过主线程发出更新。要强制表与新数据一起显示,可以将其添加到闭包的末尾:self.myTable.performSelectorOnMainThread( "reloadData", withObject: nil, waitUntilDone: false)
关于swift - 将NSData(contentsOfUrl)转换为NSURLSession吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32500715/