Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如果任务被取消,则不要执行块_Ios_Swift_Block_Nsurlsession_Nsurlsessiondatatask - Fatal编程技术网

Ios 如果任务被取消,则不要执行块

Ios 如果任务被取消,则不要执行块,ios,swift,block,nsurlsession,nsurlsessiondatatask,Ios,Swift,Block,Nsurlsession,Nsurlsessiondatatask,我有MainViewController->ThumbnailViewController->ImageFullScreenViewController。顾名思义,我有一个主屏幕,从主屏幕转到显示图像集合的屏幕,在选择图像时,我会全屏打开图像 在ThumbnailViewController中,我下载了如下图像 private func getImages() { self.galleryImages.removeAll() for url in urls {

我有
MainViewController
->
ThumbnailViewController
->
ImageFullScreenViewController
。顾名思义,我有一个主屏幕,从主屏幕转到显示图像集合的屏幕,在选择图像时,我会全屏打开图像

ThumbnailViewController
中,我下载了如下图像

private func getImages() {
        self.galleryImages.removeAll()
        for url in urls {
            let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in

                // errors are handled

                if let image = UIImage(data: data) {
                    self.galleryImages.append(image!)
                }
            }
            task.resume()
            requests.append(task)
        }
    }
viewDidLoad()
中,我调用
getImages()
。在
ThumbnailViewController
视图将消失()
中,我取消正在进行的任务

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    if isMovingFromParentViewController() {
        if requests.count > 0 {
            for request in requests {
                if request is NSURLSessionDataTask {
                    let task = request as! NSURLSessionDataTask
                    task.cancel()
                }
            }
        }
    }
}
问题是,当我打开
ThumbnailViewController
并立即返回时,如果我立即打开
ThumbnailViewController
,在某些情况下,我可以看到相同图像的两个副本(很少,但可以复制)

经过调查,我发现,在
视图中取消
NSURLSessionDataTask
只会取消任务,而不会取消完成块(这就是行为)。在一些罕见的情况下,会对以前的
NSURLSessionDataTask
执行完成块,从而结束与新的
NSURLSessionDataTask
的响应混合

我该怎么办


注意:
galleryImages
是我在
ImageFullScreenViewController
UIPageViewController

中重用的单一属性。首先,您应该注意释放
ThumbnailViewController
对象。使用
弱self
声明捕获列表,它将在99%的情况下消除您的问题(如果您在其他地方没有保留
self
),尽管您的模型仍然不能完美地使用该单音

private func getImages() {
    self.galleryImages.removeAll()
    for url in urls {
        let task = NSURLSession.sharedSession().dataTaskWithURL(url) { [weak self] (data, response, error) in

            // errors are handled
            // replace self. with self?.

            if let image = UIImage(data: data) {
                self?.galleryImages.append(image!)
            }
        }
        task.resume()
        requests.append(task)
    }
}

更简单的一点是:)在将图像添加到galleryImages之前,为什么不使用galleryImages.contains(image){…}是
galleryImages
computed属性,或者它是否有任何观察者?请出示申报单。没有什么奇怪的,任务有时已经在完成的路上了;奇怪的是,它如何能够在
ThumbnailViewController
的新实例中将接收到的图像与图像数组混合。如果
galleryImages
以某种方式共享,则可能会发生这种情况。对不起。我应该提一下
galleryImages
是一个单件。我将其设置为singleton,因为我在
ImageFullScreenViewController
中为
UIPageViewController
重用了相同的数组,并按照建议修改了模型,从而解决了问题。非常感谢。除非我误解了您的建议,否则如果单个视图控制器意外地同时启动两次抓取,即使这样也不能保证正常工作。在我看来,一种更稳健的方法是a.在removeAll中用新数组替换GalleryImage,B.将其存储在块外的新变量中,C.在块内捕获该变量,而不是在self.GalleryImage,D.在主线程上运行块的内部,这样就不会有多个线程与单个可变数组发生冲突。这样,每一组请求总是填充一个新数组,并且只使用最新的数组。@dgatwood你说得对。我只是指出了现有代码中的重要问题,以及不完善的模型;我认为建议具体的其他模式过于宽泛