我目前正在使用UITableView和NSFetchResultController编写应用程序来管理tableview。
我必须多次改变我的谓词。它工作正常,但有时,当tableview重新加载时,某些单元格没有填充。
最后,我的桌面视图以:1个好细胞,2个空细胞,3个好细胞,1个空细胞。 我的数据库没有损坏,因为当我触摸一个单元格时,应用程序会获得在数据库中处理的好数据。
这个错误难以重现并让我发疯。
这是我的代码:
每次必须更改类别时加载请求的功能
//On charge la datasource
func loadFetchContoller(categorie: Categorie) {
//On set le fetchRequest
if self.fetchRequest == nil {
self.fetchRequest = NSFetchRequest(entityName: "New")
}
//On tri par date de publication
var sortDescriptor = NSSortDescriptor(key: "published_at", ascending: false)
self.fetchRequest!.sortDescriptors = [sortDescriptor]
//self.fetchRequest!.fetchBatchSize = 20
//On met à jour le predicate
let predicate = NSPredicate(format: "categorie.name = %@", categorie.name)
self.fetchRequest!.predicate = predicate
//Si le fetchResultController n'existe pas, on le crée
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: self.fetchRequest!, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
self.fetchedResultsController?.delegate = self
//On relance le fetchController
var error: NSError?
self.fetchedResultsController?.performFetch(nil)
self.tableViewNews.reloadData()
}
这里,NSFetchedResultsController的功能
func controllerWillChangeContent(controller: NSFetchedResultsController) {
self.tableViewNews.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
self.tableViewNews.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .None)
case .Update:
if let cell = self.tableViewNews.cellForRowAtIndexPath(indexPath!) {
self.tableViewNews.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
}
case .Move:
self.tableViewNews.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
self.tableViewNews.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .None)
case .Delete:
self.tableViewNews.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .None)
default:
return
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
self.tableViewNews.endUpdates()
}
最后,处理TableView的功能:
// MARK: - Table view data source
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//On retourne le nombre de données
if let arraySection = self.fetchedResultsController?.sections {
return arraySection[section].numberOfObjects
} else {
return 0
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
//On récupère la new
var new = self.fetchedResultsController?.objectAtIndexPath(indexPath) as! New
//Si on est sur les photos, on retourne tous le temps la même taille
if new.media == "photo" {
return 220.0
}
//Sinon on calcule la hauteur des strings à afficher
else {
//On récupère le texte final de la description
var lengthDescription = new.description_new.stringByConvertingHTMLToPlainText().length()
if lengthDescription > 200 {
lengthDescription = 200
}
//On récupère la description et on regarde la hauteur du texte que l'on va afficher
var description = FBAHelperController.sharedInstance.getDateInText(NSDate(timeIntervalSince1970: new.published_at.doubleValue)) + " - " + (new.description_new.stringByConvertingHTMLToPlainText() as NSString).substringToIndex(lengthDescription) + "..."
var heightTitre = new.title.heightForString(new.title, font: UIFont(name: "HelveticaNeue-Medium", size: 18.0)!, width: UIScreen.mainScreen().bounds.width - 60)
var heightDescription = new.description_new.heightForString(description, font: UIFont(name: "HelveticaNeue-Light", size: 17.0)!, width: UIScreen.mainScreen().bounds.width - 20)
return heightTitre + heightDescription + 95.0
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//On récupère la new
var new = self.fetchedResultsController?.objectAtIndexPath(indexPath) as! New
//CELLULE AVEC PHOTO
if new.media == "photo" {
//On crée la cellule
let cell = tableView.dequeueReusableCellWithIdentifier("FBATeamInfoWithImageTableViewCell", forIndexPath: indexPath) as! FBATeamInfoWithImageTableViewCell
self.configureCell(cell, atIndexPath: indexPath)
return cell
}
//CELLULE SANS PHOTO
else {
//On crée la cellule
let cell = tableView.dequeueReusableCellWithIdentifier("FBATeamInfoWithoutImageTableViewCell", forIndexPath: indexPath) as! FBATeamInfoWithoutImageTableViewCell
self.configureCell(cell, atIndexPath: indexPath)
return cell
}
}
configureCell()是我用来填充单元格的标签(label,imageview等...à