ios - Using UICollectionView with CoreData and NSFetchedResultsController -
i started project exploring swift little bit. want implement collection view using nsfetchedresultscontroller data out of coredata database. wanted use example https://github.com/ashfurrow/uicollectionview-nsfetchedresultscontroller , implement similar in swift. don't need of move events implemented following:
first of created class save changes made:
class changeitem{ var index:nsindexpath var type:nsfetchedresultschangetype init(index: nsindexpath, type: nsfetchedresultschangetype){ self.index = index self.type = type } }
within collection view controller use 2 arrays save changes temporarily
var sectionchanges:[changeitem] = [] var objectchanges:[changeitem] = []
then wait fetchedresultscontroller change after changes on coredata database made
func controller(controller: nsfetchedresultscontroller, didchangeobject anobject: anyobject, atindexpath indexpath: nsindexpath?,forchangetype type: nsfetchedresultschangetype, newindexpath: nsindexpath?) { var item:changeitem? if(type == nsfetchedresultschangetype.insert){ item = changeitem(index: newindexpath!, type: type) }else if(type == nsfetchedresultschangetype.delete){ item = changeitem(index: indexpath!, type: type) }else if(type == nsfetchedresultschangetype.update){ item = changeitem(index: indexpath!, type: type) } if(item != nil){ self.objectchanges.append(item!) } } func controller(controller: nsfetchedresultscontroller, didchangesection sectioninfo: nsfetchedresultssectioninfo, atindex sectionindex: int, forchangetype type: nsfetchedresultschangetype) { var item:changeitem? if(type == nsfetchedresultschangetype.insert || type == nsfetchedresultschangetype.delete || type == nsfetchedresultschangetype.update){ item = changeitem(index: nsindexpath(forrow: 0, insection: sectionindex), type: type) } if(item != nil){ self.sectionchanges.append(item!) } }
after changes applied fetchedresultscontroller perform didchangecontent method
func controllerdidchangecontent(controller: nsfetchedresultscontroller) { println("something happened") self.collectionview!.performbatchupdates({ () -> void in while(self.sectionchanges.count > 0 || self.objectchanges.count > 0){ self.insertsections() self.insertitems() self.updateitems() let delips = self.deletesections() self.deleteitems(delips) } }, completion: { (done) -> void in if(done){ println("done") self.collectionview.reloaddata() }else{ println("not done") self.collectionview.reloaddata() } if(self.fetchedresultscontroller.sections != nil && self.fetchedresultscontroller.sections?.count > 0){ println("number of items in first section \(self.fetchedresultscontroller.sections![0].count)") } }) self.deselectall() self.collectionview.reloaddata() if(self.fetchedresultscontroller.sections != nil && self.fetchedresultscontroller.sections!.count > 0){ in 1 ..< self.fetchedresultscontroller.sections!.count{ if(self.fetchedresultscontroller.sections!.count > 0){ println(self.fetchedresultscontroller.sections![i].numberofobjects ) } } } }
which again calls following methods
private func deletesections()->nsindexset{ var deletes = self.sectionchanges.filter({ (item) -> bool in if(item.type == nsfetchedresultschangetype.delete){ let index = (self.sectionchanges nsarray).indexofobject(item) self.sectionchanges.removeatindex(index) return true } return false }) [changeitem] var indexset:nsmutableindexset = nsmutableindexset() del in deletes{ indexset.addindex(del.index.section) } if(indexset.count > 0 && self.collectionview.numberofsections() > 0){ self.collectionview.deletesections(indexset) } return indexset } private func insertsections(){ var inserts = self.sectionchanges.filter({ (item) -> bool in if(item.type == nsfetchedresultschangetype.insert){ let index = (self.sectionchanges nsarray).indexofobject(item) self.sectionchanges.removeatindex(index) return true } return false }) [changeitem] var indexset:nsmutableindexset = nsmutableindexset() ins in inserts{ indexset.addindex(ins.index.section) } if(indexset.count > 0){ println("adding \(indexset.count) section") println(indexset) self.collectionview.insertsections(indexset) self.collectionview.reloadsections(indexset) } } private func deleteitems(deletedsections:nsindexset?){ var deletes = self.objectchanges.filter({ (item) -> bool in if(item.type == nsfetchedresultschangetype.delete){ let index = (self.objectchanges nsarray).indexofobject(item) self.objectchanges.removeatindex(index) return true } return false }) [changeitem] var indexpaths:[nsindexpath] = [] del in deletes{ if(del.index.section < self.fetchedresultscontroller.sections?.count){ if(deletedsections == nil || deletedsections!.containsindex(del.index.section)){ indexpaths.append(del.index) } } } /*indexpaths = indexpaths.sorted({ (a, b) -> bool in if(a.section >= b.section && a.row >= b.row){ return true } return false }) println(indexpaths)*/ //self.collectionview.numberofitemsinsection(0) if(indexpaths.count > 0){ println("deleting \(indexpaths.count) items") self.collectionview.deleteitemsatindexpaths(indexpaths) } } private func updateitems(){ var updates = self.objectchanges.filter({ (item) -> bool in if(item.type == nsfetchedresultschangetype.update){ let index = (self.objectchanges nsarray).indexofobject(item) self.objectchanges.removeatindex(index) return true } return false }) [changeitem] var indexpaths:[nsindexpath] = [] update in updates{ indexpaths.append(update.index) } if(indexpaths.count > 0 ){ println("did update on \(indexpaths.count) items") self.collectionview.reloaditemsatindexpaths(indexpaths) } } private func insertitems(){ var inserts = self.objectchanges.filter({ (item) -> bool in if(item.type == nsfetchedresultschangetype.insert){ let index = (self.objectchanges nsarray).indexofobject(item) self.objectchanges.removeatindex(index) return true } return false }) [changeitem] var indexpaths:[nsindexpath] = [] ins in inserts{ indexpaths.append(ins.index) } if(indexpaths.count > 0 && self.numberofsectionsincollectionview(self.collectionview) > 0){ println("adding \(indexpaths.count) items collection view \(self.collectionview.numberofitemsinsection(0))") self.collectionview.insertitemsatindexpaths(indexpaths) println("did add items") } }
deleting multiple items , sections @ time works fine (by now), inserting section not work. can see implemented output within insertsections method. number of new sections in test scenario 1 , right nsindexset 1 item:(0). in insertitems method try call numberofobjects on section 0 , following error
*** assertion failure in -[uicollectionviewdata numberofitemsinsection:], /sourcecache/uikit_sim/uikit3347.44/uicollectionviewdata.m:5942015-06-19:00:53:01.966 grocli[42533:1547866] coredata: error: serious application error. exception caught delegate of nsfetchedresultscontroller during call -controllerdidchangecontent:. request number of items in section 0 when there 0 sections in collection view userinfo (null)
thanks in advance reading long article , helping me out!
sounds issue had while ago, when using objective c.
check out
uicollectionview assertion failure
i had work around frc work collection view.
seems found same git me, here fix solves collection view issue.
https://github.com/ashfurrow/uicollectionview-nsfetchedresultscontroller/issues/13
Comments
Post a Comment