将 NSData(contentsOfUrl) 转换为 NSURLSession?

Converting NSData(contentsOfUrl) to NSURLSession?

我一直在为 watchOS 2 开发一个应用程序,我相信我的功能,它使用 NSData(contentsOfUrl) 下载一些 JSON 数据,可能太重了,导致应用程序崩溃。我的研究使我相信 NSURLSession 是可行的方法,但我无法弄清楚如何转换我的函数以便结果和 return 以相同的方式编辑。

在我的应用程序中,有一行 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() 并以相同的方式 return NSData(contentsofUrl) 做。我知道 NSURLSession 将需要一个完成处理程序或其他东西,因为它 运行 在同一个线程上,但我无法弄清楚!谢谢!

恐怕你无法按照你描述的去做。在传输整个文件之前,contentsOfURL 方法不会 return。如果您的连接速度较慢或文件很大,UI 会在主线程繁忙时出现冻结。仅对本地文件使用该方法。

您的第二次尝试似乎有两个问题:

首先,出于安全原因,默认情况下您只能加载安全 (https:) 网址。请参阅此注释:https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/

二、dataTaskWithURL不发起转账;在您通过调用 task.resume() 指示它开始之前,dataTask 不会做任何事情。在传输完所有数据后,关闭代码将由另一个线程执行。这就是为什么你不能 return 一个值。

您仍然可以创建数据数组,但需要将声明移至 class 的顶层。请记住闭包由不同的线程执行,因此您需要在闭包中将数组引用为 self.datas

如果在闭包中加载数据后需要更新UI个元素,则需要通过主线程发出更新。要强制 table 显示新数据,您可以将其添加到闭包的末尾:
self.myTable.performSelectorOnMainThread( "reloadData", withObject: nil, waitUntilDone: false)