2017-09-09 14 views
0

URLSessionDownloadTask을 사용하여 다운로드 한 이미지를 셀에 표시하는 표보기가 있습니다. 몇 가지 자습서/게시물은 특정 이미지를 다운로드하기 위해 호출 한 셀이 재사용되지 않았는지 확인하고 나중에 해당 셀의 태그를 설정하고 확인하여 이미지를 표시해야하는 일반적인 시나리오를 다루는 것을 보았습니다. 나중에 수신/수신 된 이미지의 URL을 보유하고 검사합니다.이미지보기가 있고 네트워킹을위한 모델을 전달한 셀 : 재사용하면 어떻게됩니까?

하지만 자습서/게시물에서는 네트워크 작업이 tableView(_:cellForRowAt:) 메서드의보기 컨트롤러에서 호출 된 다음 (셀의 태그가 선택되어 있는지 확인) 또는 UITableViewCell 하위 클래스에서 호출됩니다 (그러면 URL 보통 이미지가 확인됩니다). 이 경우 다운로드 작업이 완료되면 셀을 이미 다시 사용할 수있었습니다. 그러나 내 시나리오는 약간 다르며 그 또한 일어날 수 있는지에 대해 너무 명확하지 않습니다.

tableView(_:cellForRowAt:)에서 모델 개체를 셀에 전달합니다. 그런 다음 셀 자체가 아니라 다운로드 작업을 호출하는 모델입니다. 이처럼

func configureCell(_ model: MyCellModel) { 
    // Some label's texts are set here 

    model.getPicture { (picture) in 
     imageView.image = picture 
    } 
} 

그리고 getPicture : 이것은 내가 적절한 모델과 각 셀을 구성하는 tableView(_:cellForRowAt:)에서 호출 UITableViewCell의 방법입니다 그래서

func getPicture(completion: @escaping (UIImage?) -> Void) { 
    let request = URLRequest(url: url!) 
    let task = session.downloadTask(with: request, completionHandler: { (fileUrl, response, error) in 
     if let data = try? Data(contentsOf: fileUrl), let image = UIImage(data: data) { 
      DispatchQueue.main.async { 
       completion(image) 
      } 
     } else { 
      DispatchQueue.main.async { 
       completion(nil) 
      } 
     } 
    }) 

    task.resume() 
} 

, 호출 될 때 tableView(_:cellForRowAt:) 및 세포입니다 재사용하면 새로운 모델을 "주입"합니다. 그리고 그 모델은 그 순간에 세포가 필요로하는 그림을 다운로드하기 위해 호출을 수행합니다. 셀에 모델에 대한 참조가 없습니다.

여기에서 셀이 재사용되기 전에 필요한 이미지를 얻고 새 셀을 호출 할 수 있습니까?

편집 : 어쩌면 내가 여기와 관련된 어떤 더 설명해야합니다 : 내 시나리오, 그것이 내가 이미지를 다운로드를 시작하면 문제가되지 않습니다, 다음 셀은 재사용하고 그 모델 "다이"및됩니다 다운로드가 완료되지 않았거나 더 이상 이미지가 필요 없기 때문에 셀에 그런 이미지가 표시되지 않습니다.

내 관심사는 반대입니다. 셀이 이미지 다운로드를 시작하고 이미지가 표시되기 전에 셀을 다시 사용하고 새 모델을 삽입하면 이전 모델이 삭제된다는 사실을 이해합니다. 하지만, 그 완료 폐쇄 여전히 호출 할 수 있습니다, 그리고 세포에 더 이상 필요 없어 전 이미지를 얻을 수 있습니까? 아마도 @escaping일까요? 이 시나리오에서 셀에 어떤 이미지가 나타나는지 확인해야합니까?

답변

0

셀이 데이터를 처리 할 수 ​​없습니다. 셀에 대한 데이터를 검색하는 모델이 있고 검색 한 후 모델이 죽습니다 (참조가 보유되지 않음).

이 경우 모델은 일종의 캐싱을 수행해야합니다. 또는 네트워킹 계층 캐싱을해야합니다.

class model { 
    func download(url: URL, completion:(img: UIImage?, error: Error?) -> Void) { 
     if let img = cache.find(url) { 
      completion(img, nil); 
     } 
     else { 
      taskManager.downloadImage(url, {(img, err) in 
       cache.put(url, img) 
       completion(img, err) 
      }); 
     } 
    } 
} 
+0

감사 :

AFNetworking이 그것을 수행하는 방법 (의사 코드)

. 이미지를 다운로드하기 시작한 다음 셀을 다시 사용하면 이미지가 필요하지 않기 때문에 이미지가 셀로 다시 전송되지 않습니다. 그래서 나는 캐시하지 않아도된다. 내 관심사는 실제로 반대입니다 : 세포가 이미지를 다운로드하기 시작하고 세포가 재사용되고 새로운 모델을 주입되는 이미지를 얻기 전에 이전 모델을 죽여야합니다.그러나 그 완성 클로저가 여전히 불려질 수 있었고, 셀에 더 이상 필요없는 이전 이미지를 넣을 수 있습니까? 어쩌면 그것의'탈출'때문에? – AppsDev

+0

@ AppsDev 모델의 deinit에서 그냥 요청을 취소하십시오. 그것은 성취되지 않으며 모든 것이 선할 것입니다. 캐싱에 관해서는 셀이 시야 범위 안팎으로 스크롤 할 때마다 동일한 이미지를 계속해서 다운로드하는 것은 좋지 않습니다. – Brandon