2016-09-16 3 views
2

У меня есть 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(). В viewWillDisappear() из 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 в viewWillDisappear отменяет только задание, но не блок завершения (который является поведением). В некоторых редких случаях блок завершения выполняется для предыдущего NSURLSessionDataTask, тем самым заканчивая смешивание с ответом нового NSURLSessionDataTask.

Как я мог справиться с этим?

Примечание: galleryImages одноэлементно свойство, которое я повторно использовать в ImageFullScreenViewController (UIPageViewController)

+0

Об одном проще: почему бы вам просто не проверить, существует ли изображение, прежде чем добавлять его в galleryImages, используя что-то вроде galleryImages.contains (image) {...} –

+0

Является ли вычисляемое свойство 'galleryImages' или у него есть какие-либо наблюдатели? Прошу показать объявление. Нет ничего странного, эта задача иногда уже на пути к завершению с завершением; странно, как он может смешивать полученное изображение с массивом изображений в * новом * экземпляре 'ThumbnailViewController'. Это может произойти, если «galleryImages» поделился каким-то образом. –

+0

Извините. Я должен был упомянуть. 'galleryImages' - синглтон. Я сделал это singleton, потому что, я повторно использую тот же массив для 'UIPageViewController' в' ImageFullScreenViewController' – iOS

ответ

0

Во-первых, вы должны позаботиться о выпуске ThumbnailViewController объекта. Объявите список захвата с weak self, и он, по дополнительным, удалить вашу проблему в 99% случаев (если не удерживать self в некоторых других местах), хотя ваша модель еще не совершенны с этим singletone

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) 
    } 
} 
+1

. Пересмотр модели, как было предложено, решил проблему. Спасибо! – iOS

+0

Если я не понял ваше предложение, даже это не гарантируется, что оно будет работать корректно, если один контроллер просмотра случайно начнет два извлечения одновременно. IMO, более надежным подходом было бы A. заменить galleryImages новым массивом в removeAll, B. сохранить в новой переменной * вне * блока, C. захватить эту переменную внутри блока вместо self.galleryImages, D. запустите кишки блока в основной теме, чтобы у вас не было нескольких потоков, сбрасывающих один управляемый массив. Таким образом, каждый набор запросов всегда заполняет новый массив, и используется только последнее. – dgatwood

+0

@dgatwood вы правы. Я просто указал на важный вопрос о существовавшем кодексе и на несовершенство модели; Я решил, что предложение конкретной другой модели будет слишком широким –

Смежные вопросы