How to destroy a singleton in Swift?
I create a singleton like this:
class MyManager {
private static let sharedInstance = MyManager()
class var sharedManager : MyManager {
return sharedInstance
}
}
Just a simple example on how to dispose the current instance of a Singleton:
import UIKit
class AnyTestClass
{
struct Static
{
private static var instance: AnyTestClass?
}
class var sharedInstance: AnyTestClass
{
if Static.instance == nil
{
Static.instance = AnyTestClass()
}
return Static.instance!
}
func dispose()
{
AnyTestClass.Static.instance = nil
print("Disposed Singleton instance")
}
func saySomething()
{
print("Hi")
}
}
// basic usage
AnyTestClass.sharedInstance.saySomething()
AnyTestClass.sharedInstance.dispose()
Hope it might help.
If you want to be able to destroy it, make it an optional. And don't use ! to force unwrap like in brduca answer: it wouldn't be thread safe. This answer is safer:
class MyManager {
private static var sharedInstance: MyManager?
class var sharedManager : MyManager {
guard let sharedInstance = self.sharedInstance else {
let sharedInstance = MyManager()
self.sharedInstance = sharedInstance
return sharedInstance
}
return sharedInstance
}
class func destroySharedManager() {
sharedInstance = nil
}
}
Basic usage:
// do something with singleton
AnyTestClass.sharedManager.doSomething()
// destroy singleton
AnyTestClass.destroySharedManager()
// do something with new singleton
AnyTestClass.sharedManager.doSomething()
You don't destroy a singleton. A singleton is created the first time anyone needs it, and is never destroyed as long as the application lives.
Related
I'm trying to make a shared instance but it says that not allowed!
please see the image below and give me the advice
Use
static let sharedInstance = ModelManager()
and then declare your initializer as private
private init() {
database = FMDatabase(init: SomeObject)
}
Try to do it this way:
class SomeSingleton {
internal static let sharedInstance = SomeSingleton()
// Your singleton properties
var name = ""
private init() { }
}
Then you can access it like:
SomeSingleton.sharedInstance.name = "John"
let currentName = SomeSingleton.sharedInstance.name
You are not allowed to access instance properties on class or static functions. A workaround would be to make the sharedInstance property a static property.
static let sharedInstance = ModelManager()
Try to code formate bellow :-
class var sharedInstance: YourClass {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: YourClass? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = YourClass()
}
return Static.instance!
}
Method to return shared instance
class var sharedInstance :YourClass {
struct Singleton {
static let instance = YourClass()
}
return Singleton.instance
}
Accessing shared instance:
let sharedInstance = YourClass.sharedInstance()
Check this link for more Singleton pattern in Swift
Singleton instance: Use struct with computed property of a classs instead
class MyClass :NSObject{
class var sharedInstance : MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
// do other stuff here
func getCustomerLists()-> Any{
// return
}
}
Accessing:
MyClass.sharedInstance. getCustomerLists()
class mySuperClass{
static var sharedInstance = mySuperClass()
var test = "hello"
}
In this little snippet, I am setting a static var to mySuperClass() to create a simple singleton.
Is there a way to do this without using the class name mySuperClass?
I ask, because I want to subclass something like this and have the subclass create a sharedInstance of itself and NOT of the super class which is what it does.
Full code here (playground-able):
import Cocoa
class mySuperClass{
static var sharedInstance = mySuperClass()
var test = "hello"
}
class mySubClass:mySuperClass{
override init() {
super.init()
test = "hello from subclass"
}
}
print(mySuperClass.sharedInstance.test)
print(mySubClass.sharedInstance.test) //prints test from mySuperClass not subClass
In other words you want to subclass a Singleton.
Let me know if this does solve your problem.
class MySuperClass {
private static let superClassInstance = MySuperClass()
class var sharedInstance: MySuperClass { return superClassInstance }
private init() { }
var test = "hello"
}
class MySubClass: MySuperClass {
private static let subClassInstance = MySubClass()
override class var sharedInstance: MySubClass { return subClassInstance }
private override init() {
super.init()
test = "hello from subclass"
}
}
print(MySuperClass.sharedInstance.test) // "hello"
print(MySubClass.sharedInstance.test) // "hello from subclass"
I'm coding an app involving singletons and I'm trying to access the singleton file from other files in my app. Here's my code:
Singleton.swift
class Singleton {
static let sharedInstance = Singleton()
private init() {
// Private initialization to ensure just one instance is created.
}
}
OutofQuestionsVC.swift
class OutofQuestionsVC: UIViewController {
let mysingleton = Singleton.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
mysingleton.resetQuestions()
// Do any additional setup after loading the view.
}
}
Design-Patterns-In-Swift project on github has an example
https://github.com/ochococo/Design-Patterns-In-Swift/blob/master/source/creational/singleton.swift
Example:
class DeathStarSuperlaser {
static let sharedInstance = DeathStarSuperlaser()
private init() {
// Private initialization to ensure just one instance is created.
}
}
Usage:
let laser = DeathStarSuperlaser.sharedInstance
For setting your class you can do it this way:
class Singelton {
class var sharedSingelton : Singelton {
struct Static {
static let instance : Singelton = Singelton()
}
return Static.instance
}
}
And for initializing (will be done automatically, if you access the singleton for the first time. Second time and so on the instance will be returned) you can do:
let singelton = Singelton.sharedSingelton
OR only
Singelton.sharedSingelton
I am trying to make a subclass of AFHTTPSessionManager using Swift. According to the documentation, making a singleton instance of your subclass is recommended. I understand how to make a singleton in Swift, but I need to be able to initialize my singleton with a base URL.
class ZRUserAuthenticationHTTPSessionManager: AFHTTPSessionManager {
class var sharedManager: ZRUserAuthenticationHTTPSessionManager {
struct StaticManager {
static var instance: ZRUserAuthenticationHTTPSessionManager? = nil
static var onceToken: dispatch_once_t = 0
}
if (StaticManager.instance == nil) {
dispatch_once(&StaticManager.onceToken) {
StaticManager.instance = ZRUserAuthenticationHTTPSessionManager(baseURL: myURL)
}
}
return StaticManager.instance!
}
}
How do I allow my singleton instance to be initialized with a configureable parameter?
Thanks
I've figured out how to do this.
public class func createSharedManager(baseURL: NSURL!) -> ZRUserAuthenticationHTTPSessionManager {
StaticManager.instance = ZRUserAuthenticationHTTPSessionManager(baseURL: baseURL)
return StaticManager.instance!
}
public class var sharedManager: ZRUserAuthenticationHTTPSessionManager? {
return StaticManager.instance
}
private struct StaticManager {
static var instance: ZRUserAuthenticationHTTPSessionManager? = nil
}
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.
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
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()
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()