Singleton in Swift

swift singleton with parameters
singleton in swift 4 stackoverflow
disadvantages of singleton in swift
swift singleton dependency injection
swift singleton thread safe
singleton struct swift
swift singleton vs static class
swift singleton init

I've been trying to implement a singleton to be used as a cache for photos which I uploaded to my iOS app from the web. I've attached three variants in the code below. I tried to get variant 2 working but it is causing a compiler error which I do not understand and would like to get help on what am I doing wrong. Variant 1 does the caching but I do not like the use of a global variable. Variant 3 does not do the actual caching and I believe it is because I am getting a copy in the assignment to var ic = ...., is that correct?

Any feedback and insight will be greatly appreciated.

Thanks, Zvi

import UIKit

private var imageCache: [String: UIImage?] = [String : UIImage?]()

class ImageCache {
    class var imageCache: [String : UIImage?] {
        struct Static {
            static var instance: [String : UIImage?]?
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            Static.instance = [String : UIImage?]()
        }
        return Static.instance!
    }
}

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(data: NSData(contentsOfURL: NSURL(string: "http://images.apple.com/v/iphone-5s/gallery/a/images/download/photo_1.jpg")!)!)

        //variant 1 - this code is working
        imageCache["photo_1"] = imageView.image
        NSLog(imageCache["photo_1"] == nil ? "no good" : "cached")

        //variant 2 - causing a compiler error on next line: '@lvalue $T7' is not identical to '(String, UIImage?)'
        //ImageCache.imageCache["photo_1"] = imageView.image
        //NSLog(ImageCache.imageCache["photo_1"] == nil ? "no good" : "cached")

        //variant 3 - not doing the caching
        //var ic = ImageCache.imageCache
        //ic["photo_1)"] = imageView.image
        //NSLog(ImageCache.imageCache["photo_1"] == nil ? "no good" : "cached")
    }
}

The standard singleton pattern is:

final class Manager {
    static let shared = Manager()

    private init() { ... }

    func foo() { ... }
}

And you'd use it like so:

Manager.shared.foo()

Credit to appzYourLife for pointing out that one should declare it final to make sure it's not accidentally subclassed as well as the use of the private access modifier for the initializer, to ensure you don't accidentally instantiate another instance. See https://stackoverflow.com/a/38793747/1271826.

So, returning to your image cache question, you would use this singleton pattern:

final class ImageCache {

    static let shared = ImageCache()

    /// Private image cache.

    private var cache = [String: UIImage]()

    // Note, this is `private` to avoid subclassing this; singletons shouldn't be subclassed.

    private init() { }

    /// Subscript operator to retrieve and update cache

    subscript(key: String) -> UIImage? {
        get {
            return cache[key]
        }

        set (newValue) {
            cache[key] = newValue
        }
    }
}

Then you can:

ImageCache.shared["photo1"] = image
let image2 = ImageCache.shared["photo2"])

Or

let cache = ImageCache.shared
cache["photo1"] = image
let image2 = cache["photo2"]

Having shown a simplistic singleton cache implementation above, we should note that you probably want to (a) make it thread safe by using NSCache; and (b) respond to memory pressure. So, the actual implementation is something like the following in Swift 3:

final class ImageCache: NSCache<AnyObject, UIImage> {

    static let shared = ImageCache()

    /// Observer for `UIApplicationDidReceiveMemoryWarningNotification`.

    private var memoryWarningObserver: NSObjectProtocol!

    /// Note, this is `private` to avoid subclassing this; singletons shouldn't be subclassed.
    ///
    /// Add observer to purge cache upon memory pressure.

    private override init() {
        super.init()

        memoryWarningObserver = NotificationCenter.default.addObserver(forName: .UIApplicationDidReceiveMemoryWarning, object: nil, queue: nil) { [weak self] notification in
            self?.removeAllObjects()
        }
    }

    /// The singleton will never be deallocated, but as a matter of defensive programming (in case this is
    /// later refactored to not be a singleton), let's remove the observer if deallocated.

    deinit {
        NotificationCenter.default.removeObserver(memoryWarningObserver)
    }

    /// Subscript operation to retrieve and update

    subscript(key: String) -> UIImage? {
        get {
            return object(forKey: key as AnyObject)
        }

        set (newValue) {
            if let object = newValue {
                setObject(object, forKey: key as AnyObject)
            } else {
                removeObject(forKey: key as AnyObject)
            }
        }
    }

}

And you'd use it as follows:

ImageCache.shared["foo"] = image

And

let image = ImageCache.shared["foo"]

For Swift 2.3 example, see previous revision of this answer.

Managing a Shared Resource Using a Singleton, You use singletons to provide a globally accessible, shared instance of a class. Learn how Cocoa error parameters are converted to Swift throwing methods. Home » Blog » App Development » Singletons In Swift Explained. Singletons In Swift Explained Written by Reinder de Vries on January 10 2019 in App Development. A singleton is a class of which exactly one instance exists, that can be globally accessed.

Swift 3:

class SomeClass
{
    static let sharedInstance = SomeClass() 

    fileprivate override init() {
        //This prevents others from using the default '()' initializer
        super.init()
    }

    func sayHello()
    { 
        print("Hello!")
    }   
}

Invoke some Method:

SomeClass.sharedInstance.sayHello() //--> "Hello"

Invoke some Method by creating a new class instance (fails):

SomeClass().sayHello() //--> 'SomeClass' cannot be constructed it has no accessible initailizers

Singletons In Swift (How To) – LearnAppMaking, In this article we'll dive into singletons in Swift. You learn what the singleton design pattern is, why it's useful, and when it's smart to use it. What is a singleton in Swift? First of all, let’s clarify the definition of a Swift singleton. Part of the confusion about singletons comes from the unclear distinction between global variables, singletons, and shared instances. On Wikipedia, the singleton pattern is defined as:

Following are the two different approaches to create your singleton class in swift 2.0

Approach 1) This approach is Objective C implementation over swift.

import UIKit

class SomeManager: NSObject {

       class var sharedInstance : SomeManager {

              struct managerStruct {

                   static var onceToken : dispatch_once_t = 0
                   static var sharedObject : SomeManager? = nil
              }

              dispatch_once(&managerStruct.onceToken) { () -> Void in
                   managerStruct.sharedObject = SomeManager()
              }
              return managerStruct.sharedObject!
       }

       func someMethod(){
              print("Some method call")
       }
 }

Approach 2) One line Singleton, Don't forget to implement the Private init (restrict usage of only singleton)

import UIKit

class SomeManager: NSObject {

       static let sharedInstance = SomeManager()

       private override init() {

       }

       func someMethod(){
            print("Some method call")
       }
  }

Call the Singleton method like :

  SomeManager.sharedInstance.someMethod()

What is a singleton?, What is a singleton? Swift version: 5.2. Paul Hudson @twostraws May 28th 2019. Singletons are objects that should only ever be created once, then shared� Singleton is a design pattern that is very popular in development. Most of the developers are using this design pattern. This is very simple, common and easy to use in your project. It initializes…

Swift-5

To create a singleton class:

import UIKit

final class SharedData: NSObject {
   static let sharedInstance = SharedData()

   private override init() { }

   func methodName() { }
}

To access

let sharedClass = SharedClass.sharedInstance

OR

SharedClass.sharedInstance.methodName()

Singleton Class in Swift. Getting started with Singleton Class. |…, Singleton is a design pattern that is very popular in development. Most of the developers are using this design pattern. This is very simple,� Swift-5. To create a singleton class: import UIKit final class SharedData: NSObject { static let sharedInstance = SharedData() private override init() { } func methodName() { } } To access . let sharedClass = SharedClass.sharedInstance OR. SharedClass.sharedInstance.methodName()

Swift Singletons: A Design Pattern to Avoid (With Examples), Singletons allow a class to access a shared resource without making it clear to external objects. A developer that is not familiar with the internal� Singleton pattern in Swift. Full code example in Swift with detailed comments and explanation. Singleton is a creational design pattern, which ensures that only one object of its kind exists and provides a single point of access to it for any other code.

Singletons in Swift, If you're not familiar, a singleton is an object which is instantiated exactly once. Only one copy of this object exists and the state is shared and reachable by any� The below Swift code example demonstrates how to implement the Singleton Design Pattern in Swift. Singleton Design Pattern guarantees that only one Object of a class exists in the system even if a developer attempts to create multiple instances of it.

Design Patterns: Singleton in Swift, Singleton pattern in Swift. Full code example in Swift with detailed comments and explanation. Singleton is a creational design pattern, which ensures that only� The Singleton in Swift. Class: An object defined in Swift, using pass-by-reference semantics. Design pattern: A solution to frequently occurring problems in software design.

Comments
  • Why are you using [String: UIImage?] instead of [String: UIImage]? I think that's probably the source of the trouble you're having.
  • Note that you don't need to use dispatch_once - read here
  • just FTR, DLImageLoader is an incredible caching library, and is now in Swift. it's priceless...
  • Thanks Rob, your solution is great. Do you know if it's possible to keep them between launches? With NSUserDefaults for example? I'm not sure this is the best solution.
  • @MarieDm - NSUserDefaults is probably not the right place for this sort of stuff. I manually write stuff to .CachesDirectory (from either NSFileManager method URLForDirectory or within NSSearchPathForDirectoriesInDomains). BTW, this answer predated Swift 1.2, but I have modified it with simpler singleton pattern possible in current versions of Swift.