swift2 从网路上下载json 令人不解的问题一问,有关task.resume()

陳尹
  • 348

有关 前面的程式我就不写了,我po 我一直解决不了 跟不了解的部份
我从网路上下载一段json 如下

request.HTTPBody = try! postString.dataUsingEncoding(NSUTF8StringEncoding)
    
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in
        if error != nil {
            print("\(error)")  //為什麼這行要加slef
            return
        }
        do {
            let myJSON:AnyObject? = try NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments)
            var iCount:NSInteger = (myJSON?.count)! as NSInteger
            for var i = 0; i < iCount; i++ {
                tmpUrl = self.webURL as String + (myJSON![i]["photo"] as? String)!
               self.webPhoto.append(self.myFunc.calculateImage(UIImageView(image: UIImage(named:"1.jpg")), W: bannerW, H: bannerH))  //Question 1
               
            }
            print(self.webPhoto)
            print(myJSON)
        }
        catch {
            print(error)
        }
    }
    task.resume()
    print(myJSON) // question2

Question1: 如程式中question1
为什么 webPhoto 跟myfunc 都要加self.

Question2:前面打印 myJSON 或 webPhoto都是有内容的

到在 task.resum()之后

打印出来的都变成了空值
如果需要 myJSON 跟 webPhoto 要怎么写

回复
阅读 2.5k
1 个回答
✓ 已被采纳

其实你的这两个问题是相关的, 都是由 closure (或者在 objective c 里叫做 block)引起的,你可以在网上找一下这相关的知识补充一下。

  1. 为什么要加 self 的问题,上面的下载 json 的 task 就是一个 closure,它是会被异步执行的,排在一个队列里等着,但是函数调用是立即返回的。closure 需要把它自己需要的上下文内容 capture 起来(增持引用计数),以防万一它实际执行的时候,需要的数据已经被释放,你这个例子里,closure 实际执行的时候需要调用 self 的两个方法,所以它要把 self capture 起来。强制你必须要写 self 也是让你在写代码的时候意识到这里可能会出现的问题,比如说 self 的引用计数被加 1 了,会不会导致循环引用之类的。

  2. 接着上个问题,那个 task 是异步执行的,task.resum() 的调用会立即返回,这个调用的作用就是把实际的任务挂载到一个队列里,之后才会被实际执行(可能是别的线程在执行,所以这里才不会卡住),所以 task.resum() 之后的那个 print 是紧接着就被调用的,但是 closure 里面的 print 却需要等到这个任务实际被执行的时候才会被调用。你可以注意一下两个打印实际发生的顺序,一定是第二个先出现,第一个后出现,虽然他们在代码里的位置是第一个在前面,但是执行的顺序确实反过来的。

举个接近的例子,比如说那个 task 是烧热水,那 task.resum() 对应的就是按热水器上的开关,按完开关后,热水器知道它需要烧热水了,这时候你就不管它了,你去拿了个杯子,或者去收拾了一下垃圾等等,烧热水这件事情就是个异步事件,并不是按了开关之后立即就能有一杯热水的。

至于“如果需要 myJSON 跟 webPhoto 要怎么写”,这个问题,你可以在 closure 里面进行需要 myJSON 之后的操作,或者使用 RxSwift/ReactiveCocoa等把这种异步的操作转变成类似同步的代码来使用,这个话题太大,就不细说了,你有兴趣的话,可以去看一下这两个库。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏