0

For our iOS programming class we must make a framework for Swift iOS. We had the idea of a framework simplifying CoreData manipulation. I began by creating a class where you put the NSManagedObjectContext created in AppDelegate at the beginning, so you don't have to write this long (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext anymore.

open class SimpleCoreData {
    var context: NSManagedObjectContext

    init(context: NSManagedObjectContext) {
        self.context = context
    }

    func delete(entity: NSManagedObject) /*-> Bool*/ {
        // some code
    }

    func getAll(entityClass: NSManagedObject.Type) throws ->     [NSManagedObject]? {
        // some code
    }

    func create(entityDescr: NSManagedObject.Type) -> NSManagedObject? {
        // some code
    }

But I would like it to be accessible from everywhere in the application, and this simplification would be useless if you have to instantiate this each time.

I was first thinking about a singleton, but I recently learned it wasn't a good practice.

So do you know any solution to make this accessible from everywhere in the client app? Or maybe singleton is okay in this case?

Ahmad F
  • 26,570
  • 13
  • 76
  • 124
CodingMouse
  • 73
  • 12
  • 1
    "I was first thinking about a singleton, but I recently learned it wasn't a good practice.", why? – Ahmad F Jan 29 '18 at 13:40
  • 3
    There are problems with singletons (mostly around code reuse and some kinds of unit testing), but until you've worked in iOS long enough to run into the problems and can judge the other solutions, you shouldn't avoid them just because you heard they were bad. I've been developing Cocoa for over 10 years and I use singletons all the time. If you're new to iOS, they are absolutely the best way to get started. Most of the replacements are complicated (sometimes over-complicated). – Rob Napier Jan 29 '18 at 13:49
  • @AhmadF https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – CodingMouse Jan 29 '18 at 13:49
  • BTW, you're completely correct to avoid the `UIApplication.shared.delegate` piece. That *is* a very bad pattern. If you find yourself saying `as! AppDelegate` anywhere, you are almost certainly using the application delegate incorrectly. https://stackoverflow.com/questions/828827/what-describes-the-application-delegate-best-how-does-it-fit-into-the-whole-con/829591#829591 By the looks of it, you're on exactly the right track and have the right instincts. – Rob Napier Jan 29 '18 at 13:51
  • 1
    Note that Cocoa doesn't usually use the singleton pattern being discussed there. We mostly use a shared instance pattern. It's a small but important difference. (There *can* be many NotificationCenters, and you are actually free to create more if you want; you just generally use the `default` one.) Some of the complaints there can apply in iOS, but avoiding those problems very often causes more problems than it solves in iOS. Different platforms react to different patterns differently. – Rob Napier Jan 29 '18 at 13:55
  • 1
    (And after you've actually run into a few of those problems in your singleton code, and you probably will at some point, then you'll be in a good place to consider the menagerie of competing ideas in iOS. But there's a reason that Apple still teaches the shared instance approach, and even new Apple frameworks still use it. It works really well on iOS.) – Rob Napier Jan 29 '18 at 13:57
  • I'm surprised at the comments, considering the *larger* issue of misunderstanding how Frameworks should be developed. Any, *any* use/replacement of `UIApplication.shared` doesn't belong in a framework. (Well, okay, unless if the original use was misplaced.) As for the use of singletons in a framework... it's hard to say based on the current question. – dfd Jan 29 '18 at 17:13

2 Answers2

2

Keeping Rob Napier's excellent comments in mind, if you decide to avoid a singleton in this case, a common approach would be

  • Create an instance of your SimpleCoreData class in the app delegate when the app launches.
  • Have the app delegate pass this to your initial view controller. That view controller would have a SimpleCoreData property but would not create the instance-- it would expect one to be assigned by whichever code creates it, which here is the app delegate.
  • Repeat this pattern everywhere you need a SimpleCoreData. That is, when you create an object that needs a SimpleCoreData, make sure it has a property with that type, and assign a value when you create it. For view controllers, a good place to do this is in prepare(for:sender:), if you're using segues.

It's not necessary to create the SimpleCoreData in the app delegate, though. You could create it at the first point in the app hierarchy where it's needed, and pass it along from there. So if it's only needed in the second view controller in the hierarchy and in other objects loaded from there, create it in that view controller.

This doesn't make your SimpleCoreData instance available everywhere automatically, it means that you're creating one and then passing it around. Often that works fine, but as Rob notes it's not always the best approach. It can lead to passing an object along to an object that doesn't need it, because some other object that gets created later on does. For example if you need SimpleCoreData in your initial view controller but then not again until five levels down the hierarchy, you still need to pass it along every step of the way. That's an example of when a shared instance can be useful. It's not a singleton since other instances are allowed, but it's a default instance that can be used as needed.

Tom Harrington
  • 62,792
  • 9
  • 129
  • 149
  • Thank you for explaining this to me. I finally used a singleton pattern, that I may upgrade to a shared instance pattern later. – CodingMouse Jan 30 '18 at 21:05
1

I finally learned thanks to you that singletons aren't so evil, they can be used in some case, including this one, and it seemed in my case that it was a good choice. Maybe I will change it for a shared instance pattern.
So the singleton works well. Thank you everybody for your advices, I learned a lot in design patterns.

CodingMouse
  • 73
  • 12