2017-12-22 34 views
0

내 응용 프로그램은 Flickr에서 이미지 메타 데이터를 다운로드하여 이미지 데이터 형식으로 코어 데이터에 저장하고 이미지 데이터를 UIImages로 변환하는 별도의 콜렉션 뷰 컨트롤러에 표시합니다 .코어 데이터를 사용하여 CollectionViewController의 셀을 실시간으로 업데이트합니다.

나는 CollectionViewController 자체에서 Flickr로부터 새로운 imageData를 다운로드하기위한 "새로운 컬렉션"버튼을 만들었습니다.

모든 이미지를 일괄 처리로 다운로드하고 다음보기 컨트롤러 (CollectionViewController)에 표시하면 새보기 컨트롤러가 표시되면 모두 표시되므로 문제가 없습니다. 그러나 CollectionViewController 자체에서 새 imageURL을 다운로드하면 현재 이미지는 모든 새 이미지를 사용할 수있을 때까지 유지됩니다. 나는 그들이 가능한 한 빨리 그들을 대체하고 싶습니다.

다운로드가 완료되지 않고 이미지가 다운로드 될 때 표시하려고합니다.

여기 내 "newCollection"버튼입니다 :

@IBAction func newCollectionAction(_ sender: Any) { 

    pageCount += 1 

    self.deleteImages() 

    FlickrClient.sharedInstance().getImagesFromFlickr(pin: selectedPin, context: CoreDataStack.sharedInstance().context, page: pageCount, completionHandlerForGetImages: { (images, error) in 

     guard error == nil else { 
      print("There was an error getting the images") 
      return 
     } 

     if let images = images { 
      performUIUpdatesOnMain { 
       self.photos = images 
       self.collectionView.reloadData() 
      } 
     } 
    }) 
} 

내 cellForItemAt 방법 :

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath as IndexPath) as! CollectionViewCell 
    print("The image count in the pin is: \(String(describing: selectedPin.images?.count))") 
    let photo = photos[indexPath.row] 

    // Get a photo if it already exists 
    if let photo = photo { 
     performUIUpdatesOnMain { 
      cell.imageView.image = photo.getImage() 
     } 
    } 
    return cell 
} 

그리고 내 getImagesFromFlicker 방법 :

extension FlickrClient { 

func getImagesFromFlickr(pin: Pin, context: NSManagedObjectContext, page: Any, completionHandlerForGetImages: @escaping (_ images: [Images]?, _ errorString: String?) -> Void) { 

    let methodParameters = [ 
     Constants.FlickrParameterKeys.Method: Constants.FlickrParameterValues.FlickrPhotosSearch, 
     Constants.FlickrParameterKeys.APIKey: Constants.FlickrParameterValues.APIKey, 
     Constants.FlickrParameterKeys.Format: Constants.FlickrParameterValues.ResponseFormat, 
     Constants.FlickrParameterKeys.Extras: Constants.FlickrParameterValues.MediumURL, 
     Constants.FlickrParameterKeys.NoJSONCallback: Constants.FlickrParameterValues.DisableJSONCallback, 
     Constants.FlickrParameterKeys.Lat: pin.latitude as Any, 
     Constants.FlickrParameterKeys.Lon: pin.longitude as Any, 
     Constants.FlickrParameterKeys.PerPage: Constants.FlickrParameterValues.PerPage, 
     Constants.FlickrParameterKeys.Page: page 
     ] 

    taskForGetImages(methodParameters: methodParameters, latitude: pin.latitude, longitude: pin.longitude) { (results, error) in 

     var imageArray = [Images]() 

     if let error = error { 
      completionHandlerForGetImages(nil, "There was an error getting the images: \(error)") 
     } else { 

      // Create a dictionary from the data: 

     /* GUARD: Are the "photos" and "photo" keys in our result? */ 
     if let photosDictionary = results![Constants.FlickrResponseKeys.Photos] as? [String:AnyObject], let photoArray = photosDictionary[Constants.FlickrResponseKeys.Photo] as? [[String:AnyObject]] { 

      for photo in photoArray { 

       let image = Images(context: CoreDataStack.sharedInstance().context) 

       // GUARD: Does our photo have a key for 'url_m'? 
       guard let imageUrlString = photo[Constants.FlickrResponseKeys.MediumURL] as? String else { 
        completionHandlerForGetImages(nil, "Unable to find key '\(Constants.FlickrResponseKeys.MediumURL)' in \(photo)") 
        return 
       } 

       // Get metadata 
       let imageURL = URL(string: imageUrlString)! 
       let data = try? Data(contentsOf: imageURL) 
       let title = photo["title"] as? String ?? "" 


       // Assign the metadata to images NSManagedObject 
       performUIUpdatesOnMain { 
        image.imageData = (data! as NSData) 
        image.imageURL = String(describing: imageURL) 
        image.pin = pin 
        image.title = title 

        imageArray.append(image) 
       } 
      } 
     } 
      print("Networking completed") 
      completionHandlerForGetImages(imageArray, nil) 
    } 
} 
} 

Pigpocket 당신의 지혜를 요구한다!

답변

0

이미지 목록 또는 실제 이미지를 다운로드 할 것인지 여부가 다소 혼란 스럽습니다 (이미지 파일이 데이터 모델에 내장되어 있는지 또는 실제 데이터에 옵션인지는 알 수 없습니다). getImagesFromFlickr이 완료 될 때 만 발사되기 때문에

self.collectionView.reloadData() 

: 간단히 말해서

, 나는 문제에서 비롯된 생각한다. getImagesFromFlickr 메소드를 작성했는지 여부는 알 수 없습니다.

이미지 당 완료 될 때 부분 업데이트를 사용해야합니다.

다른 대안은 콜백을 사용하지 않고 NSFetchedResultsController를 사용하는 것입니다. 이것은 다소 고급 주제이지만 NSManagedObjectContext가 저장된 시점에 따라 실시간으로 업데이트 할 수 있습니다.

OnImageDone {() -> in 
tableView.beginUpdates() 
tableView.insertRows(at: [IndexPath(row: yourArray.count-1, section: 0)], with: .automatic) 
tableView.endUpdates() 
} 

이 실시간으로 업데이트 할 수있는 데이터 저장소를 필요 :

또한 변경이의 예를 조정하는 항목을 추가/제거 할 수있는 tableview 트랜잭션을 사용해야합니다.

getImagesFromFlickr에 대한 자세한 정보를 제공해주십시오. 자세한 내용을 알려주십시오. NSFetchedResultsController가 응답을 할 수도 있지만, 모든 작업이 완료 될 때까지 이미지가 트랜잭션에 저장되지 않으면 아무 작업도 수행되지 않습니다.

+0

미첼! 예, 현재 코어 데이터를 가장 효율적으로 구현하는 방법에 대해 현재 NSFetchedResultsController를 사용하고 있습니다. 내가 작성한 getImagesFromFlickr 메소드로 코드를 업데이트했다. – Pigpocket

+1

@Pigpocket 나는 주된 문제를 볼 수있다.이미지 목록 다운로드 내에서 이미지 데이터를 가져 오는 중입니까? 먼저 이미지를 가져 와서 객체/이미지 캐시를 사용하여 URL 데이터를 가져와 캐시하는 것이 좋습니다. 문제는 이미지를 다운로드 할 때까지 업데이트되지 않는다는 것입니다. 적어도 목록 가져 오기와 데이터 다운로드를 분할해야합니다. 핵심 데이터에 이미지 데이터를 저장하는 것을 권장하지 않습니다. HanekeSwift에 마지막으로 사용한 좋은 이미지 캐시가있을 수 있습니다. –

+0

Ok. 나는 그것이 어떻게 작동하는지 정확히 이해하지 못한다. 그러나 나는 그것을 조사 할 것이다. 그러나 핵심 데이터에 이미지를 저장할 때까지 ... 이것은 수업을위한 프로젝트이며 요구 사항입니다. "이전에 사진이 할당 된 핀으로 사진 앨범보기가 열리면 바로 표시됩니다. 다운로드가 필요합니다. " – Pigpocket