ios - Use of NSFetchedResultsController in Clean Architecture -


i've searched answer without luck. question pretty same answer isn't clear (at least me!): which place nsfetchedresultscontroller in viper architecture?

the nsfetchedresultscontroller seems useful approach ios apps examples i've seen place @ viewcontroller layer - @ least, vc becomes delegate. in clean architecture/viper, model layer disconnected view layer , can't figure out how nsfrc used in such architecture. answer above question implies interactor should delegate doesn't make sense - managed objects surfaced interactor, rather ponsos. perhaps don't understand enough yet, (a) have place in clean architecture; , (b) if does, wants right swift implementation pattern?

this did in end. nsfetchedresultscontroller (nfrc)needs approached in 2 ways - fetching data, i.e. executing query, , notifications of changes managedobject (mo)set via delegate calls.

fetching data not fire delegate calls. so, return results of running fetch, i.e. annfrc.fetchedobjects(), re-package ponsos in worker or interactor , pass these presenter pass viewcontroller.

i found easier , conformant use datasource delegate viewcontroller (when table view part of implementation) - implement separate class viewcontroller.

this approach maintains standard vip cycle , requires no model knowledge in view layer.

handling delegate calls little more tricky. nfrc typically tied view layer handle table view data delegate requests: nfrc notifies of insert, delete, move, update changes , delegate handles appropriately. however, in vip architecture can't happen nfrc cannot attached view - lives in model layer , needs stay there.

i instantiated in store instance , made store instance nfrc delegate , implemented delegate methods as:

    func controller(_ controller: nsfetchedresultscontroller<nsfetchrequestresult>, didchange anobject: any, @ indexpath: indexpath?, type: nsfetchedresultschangetype, newindexpath: indexpath?) { print("item changed")         guard let manageditem = anobject as? manageditem else {             return         }         let item = manageditem.toitem()         var eventtype: eventtype         switch type {         case .insert:             eventtype = eventtype.insert         case .delete:             eventtype = eventtype.delete         case .move:             eventtype = eventtype.move         case .update:             eventtype = eventtype.update         }          let itemchangeevent = itemchangeevent(eventtype: eventtype, item: item, index: indexpath, newindex: newindexpath)         results.append(itemchangeevent)     }      func controllerwillchangecontent(_ controller: nsfetchedresultscontroller<nsfetchrequestresult>) {         results = []         print ("begin update")     }      func controllerdidchangecontent(_ controller: nsfetchedresultscontroller<nsfetchrequestresult>) {         print("end updates")         if let completionhandler = completion {             completionhandler(results)         }     } 

basically, initialise empty array (begin update), collate notifications event objects (ponsos) array (i,d,m,u), run completion handler when finished (end update). completion handler passed in part of fetch() operation , stored future use - i.e. when mo changes need notified. completion handler passed through interactor , looks like:

    func processfetchresults(itemchangeevents: [itemchangeevent]) {     let response = listitems.fetchitems.response(itemevents: itemchangeevents)     presenter?.presentfetcheditems(response: response) } 

so passes events presenter passes data source delegate can process them.

however that's not enough. efficient, data source delegate needs interact nsfrc map table view row data row @ right index path, handle section info etc. did, therefore, create protocol called dynamicdatasource , implementation of initialised interactor 'wrap' nsfrc , proxy methods. whilst model technically handed view layer, it's wrapped behind protocol , implementation converts mos ponsos. see extension (not swift extension!) of presenter layer.

    protocol listitemsdynamicdatasource: anyobject {     // mark: - helper methods     func numberofsections() -> int     func rowsinsection(_ section: int) -> int     func getitem(index: indexpath) -> listitems.fetchitems.viewmodel.displayeditem } 

if persistence store changed to, say, memory store or json layer dynamic data source implementation handle appropriately without affecting view. complex way of using nfrc think it's useful class use. simple app, it's overkill probably. however, works, , think it's good, conformant compromise.

it's worth adding i'm pretty new swift , ios development may not best code in world , there might better ways of doing it! i'm open feedback , suggestions improvement.


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -