swift - iOS - Core Data Stack as singleton with main NSManagedObjectContext -
i've seen many tutorials , me understand parent-child managed object context , other things related this. ready start using in app have question. why nobody use singleton keeping main managed object context. guess better extract core data related objects appdelegate , set own class right? in tutorial @ raywenderlich.com. still instantiate coredatastack class (no problem this, singleton must instantiate too) , when it's need set managedobjectcontext in prepareforsegue (and set first view controller appdelegate). why not remove need , use singleton coredatastack , have possible use managedobjectcontext in each controller if needed?
second , bonus question: think it's better have less code in controller , more in other classes. think helps readability. if move code controller , set example coredatastack class or other class helps core data requests , responses:
func surfjournalfetchrequest() -> nsfetchrequest { let fetchrequest = nsfetchrequest(entityname: "journalentry") fetchrequest.fetchbatchsize = 20 let sortdescriptor = nssortdescriptor(key: "date", ascending: false) fetchrequest.sortdescriptors = [sortdescriptor] return fetchrequest }
i know it's possible better? if app codes me better if in controller 1 line coredatastack.fetchrequest("journalentry", sortedkey: "date")
?
and if take code , insert singleton , created function closure? created child managed context in singleton , needed operations in there , in controller changed ui:
func exportcsvfile() { navigationitem.leftbarbuttonitem = activityindicatorbarbuttonitem() let privatecontext = nsmanagedobjectcontext(concurrencytype: .privatequeueconcurrencytype) privatecontext.persistentstorecoordinator = coredatastack.context.persistentstorecoordinator privatecontext.performblock { () -> void in var fetchrequesterror:nserror? = nil let results = privatecontext.executefetchrequest(self.surfjournalfetchrequest(), error: &fetchrequesterror) if results == nil { println("error: \(fetchrequesterror)") } let exportfilepath = nstemporarydirectory() + "export.csv" let exportfileurl = nsurl(fileurlwithpath: exportfilepath)! nsfilemanager.defaultmanager().createfileatpath(exportfilepath, contents: nsdata(), attributes: nil) var filehandleerror: nserror? = nil let filehandle = nsfilehandle(forwritingtourl: exportfileurl, error: &filehandleerror) if let filehandle = filehandle { object in results! { let journalentry = object as! journalentry filehandle.seektoendoffile() let csvdata = journalentry.csv().datausingencoding(nsutf8stringencoding, allowlossyconversion: false) filehandle.writedata(csvdata!) } filehandle.closefile() dispatch_async(dispatch_get_main_queue(), { () -> void in self.navigationitem.leftbarbuttonitem = self.exportbarbuttonitem() println("export path: \(exportfilepath)") self.showexportfinishedalertview(exportfilepath) }) } else { dispatch_async(dispatch_get_main_queue(), { () -> void in self.navigationitem.leftbarbuttonitem = self.exportbarbuttonitem() println("error: \(filehandleerror)") }) } } }
i want sure aproach okay , better original. thanks
i built first core data app singleton pattern. seemed logical me because there 1 core data stack anyway. wrong, singleton pattern turned big mess quickly. added more , more code bend singleton stack works. in end gave , invested time replace singleton mess dependency injection.
here of problems encountered before dumped singleton:
since app kept important data, users requested backup functionality. restore backup switched sqlite file , create new core data stack. doing in clean way next impossible if use pull-pattern managedobjectcontext singleton. way switch core data stack tell user have restart app. followed exit()
. not elegant way handle this.
after apple added childcontexts decided rid of undo managers , context rollbacks, because never worked 100% me. changing editing viewcontrollers use child contexts discarded when user hits cancel
, incredible painful act because had mix of singleton contexts , viewcontroller local contexts in 1 viewcontroller.
editing targets of relationships had editviewcontrollers inside editviewcontroller. because created edit context inside edit viewcontrollers ended saving data main context shouldn't have been saved. it's bit complicated explain, second viewcontroller saved stuff new objects main context if user in outer edit viewcontroller hit cancel. lead orphaned objects. added more code bend singleton in way make less of singleton.
i had csv import function , wanted preview data user before press "import". build totally new infrastructure that. first parsed csv data structure duplicated core data classes. build viewcontroller display these non core data classes, more code duplication. start create core data objects when user pressed import.
after got rid of singleton pattern reuse existing data display viewcontroller. give different context, in case in-memory context contained data imported. cleaner, less duplicated code.
i guess of these problems not singletons fault. inexperienced.
still recommend against singleton core data.
would 1 line
coredatastack.fetchrequest("journalentry", sortedkey: "date")
?
you don't need singleton this. stuff should in nsmanagedobject subclass create journalentry.
and if take code , insert singleton , created function closure? created child managed context in singleton , needed operations in there , in controller changed ui:
and why don't create method doesn't require internal state @ all?
class func export(#context: nsmanagedobjectcontext, tocsvatpath path: string, progress: ((current: int, totalcount: int) -> void)?, completion: ((success: bool, error: nserror?) -> void)?) {
much more flexible.
Comments
Post a Comment