Reputation: 99
Over the past few days I've been attempting to populate a UICollectionView with new data images by pressing a 'newCollection' button from within the view that the collection view exists. I can see in my console that the data for the images is being downloaded, and I'm able to see the CV cells populated once I leave the view, then return. Any idea why the collection view cells are not updating in realtime?
Here is what I'm working with:
https://github.com/tdangles81/Virtual-Tourist/tree/detail-view
@IBAction func newCollectionBtn(sender: AnyObject) {
getNewCollection()
}
func getNewCollection(){
if let newFetch = self.fetchedResultsController.fetchedObjects{
for object in newFetch{
let newImg = object as! ImgModel
self.sharedContext.deleteObject(newImg)
}
}
FlickrRequestClient.sharedInstance().getNewGeoImgs(selectedPin)
}
var sharedContext: NSManagedObjectContext {
return CoreDataStack.sharedInstance().managedObjectContext
}
func saveContext(){
return CoreDataStack.sharedInstance().saveContext()
}
lazy var fetchedResultsController: NSFetchedResultsController = {
let fetchRequest = NSFetchRequest(entityName: "Image")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "pin == %@", self.selectedPin)
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: self.sharedContext,
sectionNameKeyPath: nil, cacheName: nil)
return fetchedResultsController
}()
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin") as? MKPinAnnotationView
if pinView == nil{
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
}else{
pinView?.annotation = annotation
}
return pinView
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let sectionInfo = self.fetchedResultsController.sections![section]
print(sectionInfo.numberOfObjects)
return sectionInfo.numberOfObjects
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("DetailCell", forIndexPath: indexPath) as! ImageCollectionCell
let image = fetchedResultsController.objectAtIndexPath(indexPath) as! ImgModel
configureUI(cell, image: image, atIndexPath: indexPath)
return cell
}
func configureUI(cell: ImageCollectionCell, image: ImgModel, atIndexPath indexPath: NSIndexPath) {
if image.image != nil{
image.loadUpdateHandler = nil
cell.flickrImageView.image = image.image!
print("Image.image \(image.image!)")
self.saveContext()
}else{
image.loadUpdateHandler = {[unowned self] () -> Void in
dispatch_async(dispatch_get_main_queue(), {
self.collectionView.reloadData()
})
}
cell.flickrImageView.image = image.image
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
if collectionView.cellForItemAtIndexPath(indexPath) != nil {
let image = fetchedResultsController.objectAtIndexPath(indexPath) as! ImgModel
print(image)
}
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
insertedIndex = [NSIndexPath]()
updatedIndex = [NSIndexPath]()
deletedIndex = [NSIndexPath]()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
insertedIndex.append(newIndexPath!)
case .Update:
updatedIndex.append(indexPath!)
case .Move:
print("Surprise!")
case .Delete:
deletedIndex.append(indexPath!)
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
collectionView.performBatchUpdates({() -> Void in
for indexPath in self.insertedIndex {
self.collectionView.insertItemsAtIndexPaths([indexPath])
}
for indexPath in self.updatedIndex {
self.collectionView.reloadItemsAtIndexPaths([indexPath])
}
for indexPath in self.deletedIndex {
self.collectionView.deleteItemsAtIndexPaths([indexPath])
}
},completion: nil)
}
func addSpinner(cellView: UICollectionViewCell, activityBool: Bool){
let activitySpinner = UIActivityIndicatorView.init(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
activitySpinner.center = cellView.center
activitySpinner.color = UIColor.whiteColor()
activitySpinner.startAnimating()
if activityBool == true{
activitySpinner.startAnimating()
cellView.addSubview(activitySpinner)
}else if activityBool == false{
activitySpinner.stopAnimating()
cellView.willRemoveSubview(activitySpinner)
}
}
func removeSpinner(){
}
}
Upvotes: 1
Views: 786
Reputation: 86
I experienced an issue in the NSFetchedResultsController behaviour. If NSPredicate is set on its fetch request, the delegate methods are not called.
Try to remove the predicate to see if you have this problem too.
I'm trying to see if it's a bug in Xcode, or some unhanded error related to faults, or if the new query token system is used in the NSFetchedResultsController class and we need to do something about it.
Upvotes: 1