2017-12-22 24 views
0

私のアプリはFlickrから画像メタデータをダウンロードし、Imagesオブジェクトの形でコアデータに保存し、imageDataをUIImagesに変換する別のコレクションビューコントローラに表示します。コアデータを使用してリアルタイムでCollectionViewControllerのセルを更新する

私は、 "new collection"ボタンを作成して、CollectionViewController自体のFlickrから新しいimageDataをダウンロードしました。

すべてのイメージを一括してダウンロードし、次のView Controller(CollectionViewController)に表示すると、新しいView Controllerが表示された時点ですべて表示されるため、問題ありません。ただし、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メソッドを記述したかどうかはわかりません。

イメージごとに部分的な更新を行う必要があります。

もう1つの方法は、コールバックを使用せずにNSFetchedResultsControllerを使用することです。これはやや高度なトピックですが、NSManagedObjectContextが保存されたときにはもちろん、リアルタイムで更新に応答することができます。

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

これはリアルタイムで更新されるデータストアを必要とする:

また変化し、このの 例を両立するために、項目を追加/削除するにはテーブルビューのトランザクションを使用する必要があります。

getImagesFromFlickrに関する詳細情報を提供してください。より具体的な情報を提供することができます。 NSFetchedResultsControllerが起動していれば、答えが返ってくるかもしれませんが、画像が最後までトランザクションに保存されていないと、何も処理されません。

+0

ありがとうミッチェル!はい、私は現在、NSFetchedResultsControllerを使用しています。コア・データを最も効率的に実装する方法について現在作業中です。私が書いたgetImagesFromFlickrメソッドでコードを更新しました。 – Pigpocket

+1

@Pigpocket私は主要な問題を見ることができます..イメージリストダウンロード内のイメージデータを取得していますか?それらを分割し、最初にイメージをフェッチし、オブジェクト/イメージキャッシュを使用してURLデータをフェッチしてキャッシュすることをお勧めします。問題は、画像がダウンロードされるまで更新されないことです。最低でも、リストの取り出しとバックグラウンドでのデータのダウンロードを分割する必要があります。コアデータに画像データを保存することはお勧めしません。 HanekeSwift最後に使用した良いイメージキャッシュを持っているかもしれない –

+0

Ok。私はそれがうまくいくかどうか分かりませんが、私はそれを調べます。しかし、コアデータに画像を保存する限り、これはクラスのプロジェクトです。これは要件です。「以前に写真が割り当てられたピンのフォトアルバムビューが開かれていると、すぐに表示されます。ダウンロードが必要です。 – Pigpocket

関連する問題