使用核心数据实时更新CollectionViewController中的单元格

问题描述 投票:0回答:1

我的应用程序从Flickr下载图像元数据,以Images对象的形式将其保存到核心数据,并将它们显示在单独的集合视图控制器中,该控制器将imageData转换为UIImages。

我创建了一个“新集合”按钮,用于从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请求你的智慧!

ios core-data uicollectionview uicollectionviewcell
1个回答
0
投票

下载是指图像列表还是实际图像(我无法判断图像文件是数据模型固有的还是实际数据可选),这有些含糊不清。

简而言之,我怀疑问题源于:

self.collectionView.reloadData()

因为它只在getImagesFromFlickr完成时触发。我不知道你是否写过方法getImagesFromFlickr。

每个图像完成后,您需要使用部分更新。

另一种方法是不使用回调atltogether并使用NSFetchedResultsController,这是一个有点高级的主题,但可以让你实时响应更新 - 当然,这取决于NSManagedObjectContext的保存时间。

您还需要使用tableview事务来添加/删除项目,以协调更改示例:

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

这将需要实时更新数据存储。

请提供有关getImagesFromFlickr的更多信息,我可以提供更多具体细节。如果您准备好了,NSFetchedResultsController可能会给出答案,但是如果图像没有保存在事务中直到完成所有操作,那么什么都不会起作用。

© www.soinside.com 2019 - 2024. All rights reserved.