J'ai lu quelques autres questions à ce sujet que le problème lié à la taille de la CollectionView. J'ai essayé d'ajuster la taille comme recommandé dans ces réponses, mais aucun d'eux ne fonctionnait. J'utilise un NSFetchedResultsController qui convolute pour moi aussi (je me demande si cela a quelque chose à voir avec le fait qu'il ne se déclenche pas).cellForItemAtIndexPath pas appelé, pas clair pour savoir pourquoi
De toute façon, le vrai problème est que je n'ai aucun contenu apparaissant pour mon UICollectionView. Il n'y a pas d'erreurs à l'exécution, simplement un écran vide. Je travaille chez Swift (évidemment).
Voici mon code du ViewController:
import UIKit
import CoreData
private let reuseIdentifier = "Family"
private var selectedFirstName:String = "Blank"
private var selectedLastName:String = "Blank"
private var selectedNumber:String = "Blank"
private var selectedEmail:String = "Blank"
class FamilyViewController: UIViewController, UICollectionViewDataSource {
var coreDataStack: CoreDataStack!
var fetchedResultsController: NSFetchedResultsController!
@IBOutlet var familyCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
//1
let fetchRequest = NSFetchRequest(entityName: "Family")
let firstNameSort =
NSSortDescriptor(key: "firstName", ascending: true)
fetchRequest.sortDescriptors = [firstNameSort]
//2
self.coreDataStack = CoreDataStack()
fetchedResultsController =
NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: coreDataStack.context,
sectionNameKeyPath: nil,
cacheName: nil)
fetchedResultsController.delegate = CollectionViewFetchedResultsControllerDelegate(collectionView: familyCollectionView)
//3
do {
try fetchedResultsController.performFetch()
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
}
func configureCell(cell: FamilyCCell, indexPath: NSIndexPath) { let family = fetchedResultsController.objectAtIndexPath(indexPath) as! Family
cell.firstNameLabel.text = family.firstName
print("configureCell ran")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
print("numberOfSectionsInCollectionView ran")
return fetchedResultsController.sections!.count
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
let sectionInfo = fetchedResultsController.sections![section]
print("numberOfItemsInSection ran")
return sectionInfo.numberOfObjects
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! FamilyCCell
print("cellForItemAtIndexPath ran")
configureCell(cell, indexPath: indexPath)
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showDetail") {
let detailVC = segue.destinationViewController as! ContactViewController
print("prepareForSegue ran")
detailVC.detailFirstName = selectedFirstName
detailVC.detailLastName = selectedLastName
detailVC.detailNumber = selectedNumber
detailVC.detailEmail = selectedEmail
}
}
}
extension FamilyViewController: UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print("didSelectItemAtIndexPath ran")
collectionView.delegate = self
let family = fetchedResultsController.objectAtIndexPath(indexPath) as! Family
selectedFirstName = family.firstName!
selectedLastName = family.lastName!
selectedNumber = family.phone!
selectedEmail = family.email!
coreDataStack.saveContext()
}
}
class CollectionViewFetchedResultsControllerDelegate: NSObject, NSFetchedResultsControllerDelegate {
// MARK: Properties
private let collectionView: UICollectionView
private var blockOperations: [NSBlockOperation] = []
// MARK: Init
init(collectionView: UICollectionView) {
self.collectionView = collectionView
}
// MARK: Deinit
deinit {
blockOperations.forEach { $0.cancel() }
blockOperations.removeAll(keepCapacity: false)
}
// MARK: NSFetchedResultsControllerDelegate
func controllerWillChangeContent(controller: NSFetchedResultsController) {
blockOperations.removeAll(keepCapacity: false)
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
guard let newIndexPath = newIndexPath else { return }
let op = NSBlockOperation { [weak self] in self?.collectionView.insertItemsAtIndexPaths([newIndexPath]) }
blockOperations.append(op)
case .Update:
guard let newIndexPath = newIndexPath else { return }
let op = NSBlockOperation { [weak self] in self?.collectionView.reloadItemsAtIndexPaths([newIndexPath]) }
blockOperations.append(op)
case .Move:
guard let indexPath = indexPath else { return }
guard let newIndexPath = newIndexPath else { return }
let op = NSBlockOperation { [weak self] in self?.collectionView.moveItemAtIndexPath(indexPath, toIndexPath: newIndexPath) }
blockOperations.append(op)
case .Delete:
guard let indexPath = indexPath else { return }
let op = NSBlockOperation { [weak self] in self?.collectionView.deleteItemsAtIndexPaths([indexPath]) }
blockOperations.append(op)
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case .Insert:
let op = NSBlockOperation { [weak self] in self?.collectionView.insertSections(NSIndexSet(index: sectionIndex)) }
blockOperations.append(op)
case .Update:
let op = NSBlockOperation { [weak self] in self?.collectionView.reloadSections(NSIndexSet(index: sectionIndex)) }
blockOperations.append(op)
case .Delete:
let op = NSBlockOperation { [weak self] in self?.collectionView.deleteSections(NSIndexSet(index: sectionIndex)) }
blockOperations.append(op)
default: break
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
collectionView.performBatchUpdates({
self.blockOperations.forEach { $0.start() }
}, completion: { finished in
self.blockOperations.removeAll(keepCapacity: false)
})
}
}
J'ai des déclarations d'impression confirmant que le cellForItemAtIndexPath ne fonctionne pas. Des idées? Je me rends compte que c'est assez spécifique et j'ai donné une tonne de code, mais je ne sais pas trop d'où l'erreur pourrait provenir. Merci d'avance pour toute aide.
I crois que j'ai fait ça. Je les ai contrôlés en cliquant dessus dans le storyboard et connecté la collection à la source de données/délégué. Quelque chose avec le code viewcontroller que je devrais brancher là-bas? Je ne le pensais pas mais je pouvais certainement me tromper. – skind
renvoyez-vous un nombre de sections et d'éléments non nul? – Sulthan
J'interroge le NSFetchedResultsController pour le nombre de sections, il devrait donc renvoyer un nombre différent de zéro. – skind