Swift initializer is inaccessible due to private protection level - swift

I'm trying to create a singleton in Swift but I'm getting this error:
initializer is inaccessible due to private protection level
Here is my code (singleton class)
class mySingleton{
private init() { }
static let sharedInstance = mySingleton()
var numbers = 0
func incrementNumberValue() {
numbers += 1
}
}
Here is where I'm calling the singleton:
override func viewDidLoad() {
super.viewDidLoad()
let single = mySingleton().sharedInstance
}
Here is the error:
Any of you know why or how I can fix this error?

Your line:
mySingleton().sharedInstance
has a typo. As written you are trying to create an instance of mySingleton and then call the sharedInstance method on the new instance. That's two mistakes.
What you actually want is:
mySingleton.sharedInstance
Now this calls the sharedInstance type constant on your mySingleton class.
BTW - it is expected that classnames begin with uppercase letters. Method and variable names should start with lowercase letters.

for using by instance object
class mySingleton{
private init() { }
static let sharedInstance = mySingleton()
var sharedInstanceByInstance: mySingleton{
return mySingleton.sharedInstance
}
//Usage: mySingleton().sharedInstanceByInstance
// or
func getShared()-> mySingleton{
return mySingleton.sharedInstance
}
//Usage: mySingleton().getShared()
}

Related

Extend Private class defined in an extension of class in Swift

TL;DR
Is it possible to extend a privately owned and defined-in-extension class, i.e. NewsParser?
Related documents
swift2 - Extension of a nested type in Swift - Stack Overflow talks about similar situation, except the nested class type is not private.
I have a class NewsPost:
class NewsPost {
var title: String?
var author: String?
var mainContent: NSAttributedString?
var data: Data? {
didSet {
let newsParser = NewsParser(delegate: self)
newsParser.parse()
}
}
// Init methods and other stuff...
}
And a NewsPost-owned class NewsParser: (in another Swift file, but this does not seem to be a factor, due to SR-631)
private extension NewsPost {
private class NewsParser {
weak var delegate: NewsPost?
// Other properties for parsing...
init(delegate: NewsPost) {
self.delegate = delegate
}
func parse() {
// parse the delegate.data and update properties in delegate (NewsPost instance)
}
// Other methods to be called for parsing...
}
}
But it does not seem to possible to extend NewsPost.NewsParser.
The following attempts do not work:
Attempt 1
Error: 'NewsParser' is inaccessible due to 'fileprivate' protection level
private extension NewsPost { // Notice the "private" prefix
class NewsParser {
weak var delegate: NewsPost?
//Other properties for parsing...
init(delegate: NewsPost) {
self.delegate = delegate
}
func parse() {
// parse the delegate.data and update properties in delegate (NewsPost instance)
}
// Other methods to be called for parsing...
}
}
Error happens in NewsPost definition:
var data: Data? {
didSet {
let newsParser = NewsParser(delegate: self) // error happens here
newsParser.parse()
}
}
Attempt 2
Error: 'NewsParser' is inaccessible due to 'private' protection level
extension NewsPost {
private class NewsParser { // Notice the "private" prefix
var delegate: NewsPost
// Other properties for parsing...
func parse() {
// parse the delegate.data and update properties in delegate (NewsPost instance)
}
// Other methods to be called for parsing...
}
}
extension NewsPost.NewsParser { // error happens here
// extensions here...
// many kinds of errors happen here
}
Is it possible to extend a privately owned and defined-in-extension class, i.e. NewsParser?
I tried your code in a playground and it worked like a charm with a private class nested in a private extension :
Called that way :
var str = "Hello, playground"
let post = NewsPost()
post.data = str.data(using: .utf8)
Your main problem is that your probably declared your private extension in a separate file and private means fileprivate for an extension. Put your extension and your NewsPostclass in the same file and your error should go away!
If you really want to extend NewsParser you have to make it internal.
Extension declaration are only valid at file scope so if you create a private class you have no way of extending it.
Note that an internal nested class would not be visible outside its target. So using Frameworks you should be able to hide your NewsParser class from your UI code.

Swift: How to create a Singleton Class in Swift 3? [duplicate]

I'm trying to work out an appropriate singleton model for usage in Swift. So far, I've been able to get a non-thread safe model working as:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
Wrapping the singleton instance in the Static struct should allow a single instance that doesn't collide with singleton instances without complex naming schemings, and it should make things fairly private. Obviously though, this model isn't thread-safe. So I tried to add dispatch_once to the whole thing:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(Static.token) { Static.instance = TPScopeManager() }
return Static.instance!
}
}
But I get a compiler error on the dispatch_once line:
Cannot convert the expression's type 'Void' to type '()'
I've tried several different variants of the syntax, but they all seem to have the same results:
dispatch_once(Static.token, { Static.instance = TPScopeManager() })
What is the proper usage of dispatch_once using Swift? I initially thought the problem was with the block due to the () in the error message, but the more I look at it, the more I think it may be a matter of getting the dispatch_once_t correctly defined.
tl;dr: Use the class constant approach if you are using Swift 1.2 or above and the nested struct approach if you need to support earlier versions.
From my experience with Swift there are three approaches to implement the Singleton pattern that support lazy initialization and thread safety.
Class constant
class Singleton {
static let sharedInstance = Singleton()
}
This approach supports lazy initialization because Swift lazily initializes class constants (and variables), and is thread safe by the definition of let. This is now officially recommended way to instantiate a singleton.
Class constants were introduced in Swift 1.2. If you need to support an earlier version of Swift, use the nested struct approach below or a global constant.
Nested struct
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static let instance: Singleton = Singleton()
}
return Static.instance
}
}
Here we are using the static constant of a nested struct as a class constant. This is a workaround for the lack of static class constants in Swift 1.1 and earlier, and still works as a workaround for the lack of static constants and variables in functions.
dispatch_once
The traditional Objective-C approach ported to Swift. I'm fairly certain there's no advantage over the nested struct approach but I'm putting it here anyway as I find the differences in syntax interesting.
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
}
See this GitHub project for unit tests.
Since Apple has now clarified that static struct variables are initialized both lazy and wrapped in dispatch_once (see the note at the end of the post), I think my final solution is going to be:
class WithSingleton {
class var sharedInstance: WithSingleton {
struct Singleton {
static let instance = WithSingleton()
}
return Singleton.instance
}
}
This takes advantage of the automatic lazy, thread-safe initialization of static struct elements, safely hides the actual implementation from the consumer, keeps everything compactly compartmentalized for legibility, and eliminates a visible global variable.
Apple has clarified that lazy initializer are thread-safe, so there's no need for dispatch_once or similar protections
The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as dispatch_once to make sure that the initialization is atomic. This enables a cool way to use dispatch_once in your code: just declare a global variable with an initializer and mark it private.
From here
For Swift 1.2 and beyond:
class Singleton {
static let sharedInstance = Singleton()
}
With a proof of correctness (all credit goes here), there is little to no reason now to use any of the previous methods for singletons.
Update: This is now the official way to define singletons as described in the official docs!
As for concerns on using static vs class. static should be the one to use even when class variables become available. Singletons are not meant to be subclassed since that would result in multiple instances of the base singleton. Using static enforces this in a beautiful, Swifty way.
For Swift 1.0 and 1.1:
With the recent changes in Swift, mostly new access control methods, I am now leaning towards the cleaner way of using a global variable for singletons.
private let _singletonInstance = SingletonClass()
class SingletonClass {
class var sharedInstance: SingletonClass {
return _singletonInstance
}
}
As mentioned in the Swift blog article here:
The lazy initializer for a global variable (also for static members of
structs and enums) is run the first time that global is accessed, and
is launched as dispatch_once to make sure that the initialization is
atomic. This enables a cool way to use dispatch_once in your code:
just declare a global variable with an initializer and mark it
private.
This way of creating a singleton is thread safe, fast, lazy, and also bridged to ObjC for free.
Swift 1.2 or later now supports static variables/constants in classes. So you can just use a static constant:
class MySingleton {
static let sharedMySingleton = MySingleton()
private init() {
// ...
}
}
There is a better way to do it. You can declare a global variable in your class above the class declaration like this:
var tpScopeManagerSharedInstance = TPScopeManager()
This just calls your default init or whichever init and global variables are dispatch_once by default in Swift. Then in whichever class you want to get a reference, you just do this:
var refrence = tpScopeManagerSharedInstance
// or you can just access properties and call methods directly
tpScopeManagerSharedInstance.someMethod()
So basically you can get rid of the entire block of shared instance code.
Swift singletons are exposed in the Cocoa frameworks as class functions, e.g. NSFileManager.defaultManager(), NSNotificationCenter.defaultCenter(). So it makes more sense as a class function to mirror this behavior, rather than a class variable as some other solutions. e.g:
class MyClass {
private static let _sharedInstance = MyClass()
class func sharedInstance() -> MyClass {
return _sharedInstance
}
}
Retrieve the singleton via MyClass.sharedInstance().
Per the Apple documentation, it has been repeated many times that the easiest way to do this in Swift is with a static type property:
class Singleton {
static let sharedInstance = Singleton()
}
However, if you're looking for a way to perform additional setup beyond a simple constructor call, the secret is to use an immediately invoked closure:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
This is guaranteed to be thread-safe and lazily initialized only once.
Swift 4+
protocol Singleton: class {
static var sharedInstance: Self { get }
}
final class Kraken: Singleton {
static let sharedInstance = Kraken()
private init() {}
}
Looking at Apple's sample code I came across this pattern. I'm not sure how Swift deals with statics, but this would be thread safe in C#. I include both the property and method for Objective-C interop.
struct StaticRank {
static let shared = RankMapping()
}
class func sharedInstance() -> RankMapping {
return StaticRank.shared
}
class var shared:RankMapping {
return StaticRank.shared
}
In brief,
class Manager {
static let sharedInstance = Manager()
private init() {}
}
You may want to read Files and Initialization
The lazy initializer for a global variable (also for static members of
structs and enums) is run the first time that global is accessed, and
is launched as dispatch_once to make sure that the initialization is
atomic.
If you are planning on using your Swift singleton class in Objective-C, this setup will have the compiler generate appropriate Objective-C-like header(s):
class func sharedStore() -> ImageStore {
struct Static {
static let instance : ImageStore = ImageStore()
}
return Static.instance
}
Then in Objective-C class you can call your singleton the way you did it in pre-Swift days:
[ImageStore sharedStore];
This is just my simple implementation.
First solution
let SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
Later in your code:
func someFunction() {
var socketManager = SocketManager
}
Second solution
func SocketManager() -> SocketManagerSingleton {
return _SocketManager
}
let _SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
And later in your code you will be able to keep braces for less confusion:
func someFunction() {
var socketManager = SocketManager()
}
final class MySingleton {
private init() {}
static let shared = MySingleton()
}
Then call it;
let shared = MySingleton.shared
Use:
class UtilSingleton: NSObject {
var iVal: Int = 0
class var shareInstance: UtilSingleton {
get {
struct Static {
static var instance: UtilSingleton? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token, {
Static.instance = UtilSingleton()
})
return Static.instance!
}
}
}
How to use:
UtilSingleton.shareInstance.iVal++
println("singleton new iVal = \(UtilSingleton.shareInstance.iVal)")
The best approach in Swift above 1.2 is a one-line singleton, as -
class Shared: NSObject {
static let sharedInstance = Shared()
private override init() { }
}
To know more detail about this approach you can visit this link.
From Apple Docs (Swift 3.0.1),
You can simply use a static type property, which is guaranteed to be
lazily initialized only once, even when accessed across multiple
threads simultaneously:
class Singleton {
static let sharedInstance = Singleton()
}
If you need to perform additional setup beyond initialization, you can
assign the result of the invocation of a closure to the global
constant:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
I would suggest an enum, as you would use in Java, e.g.
enum SharedTPScopeManager: TPScopeManager {
case Singleton
}
Just for reference, here is an example Singleton implementation of Jack Wu/hpique's Nested Struct implementation. The implementation also shows how archiving could work, as well as some accompanying functions. I couldn't find this complete of an example, so hopefully this helps somebody!
import Foundation
class ItemStore: NSObject {
class var sharedStore : ItemStore {
struct Singleton {
// lazily initiated, thread-safe from "let"
static let instance = ItemStore()
}
return Singleton.instance
}
var _privateItems = Item[]()
// The allItems property can't be changed by other objects
var allItems: Item[] {
return _privateItems
}
init() {
super.init()
let path = itemArchivePath
// Returns "nil" if there is no file at the path
let unarchivedItems : AnyObject! = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
// If there were archived items saved, set _privateItems for the shared store equal to that
if unarchivedItems {
_privateItems = unarchivedItems as Array<Item>
}
delayOnMainQueueFor(numberOfSeconds: 0.1, action: {
assert(self === ItemStore.sharedStore, "Only one instance of ItemStore allowed!")
})
}
func createItem() -> Item {
let item = Item.randomItem()
_privateItems.append(item)
return item
}
func removeItem(item: Item) {
for (index, element) in enumerate(_privateItems) {
if element === item {
_privateItems.removeAtIndex(index)
// Delete an items image from the image store when the item is
// getting deleted
ImageStore.sharedStore.deleteImageForKey(item.itemKey)
}
}
}
func moveItemAtIndex(fromIndex: Int, toIndex: Int) {
_privateItems.moveObjectAtIndex(fromIndex, toIndex: toIndex)
}
var itemArchivePath: String {
// Create a filepath for archiving
let documentDirectories = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
// Get the one document directory from that list
let documentDirectory = documentDirectories[0] as String
// append with the items.archive file name, then return
return documentDirectory.stringByAppendingPathComponent("items.archive")
}
func saveChanges() -> Bool {
let path = itemArchivePath
// Return "true" on success
return NSKeyedArchiver.archiveRootObject(_privateItems, toFile: path)
}
}
And if you didn't recognize some of those functions, here is a little living Swift utility file I've been using:
import Foundation
import UIKit
typealias completionBlock = () -> ()
extension Array {
func contains(#object:AnyObject) -> Bool {
return self.bridgeToObjectiveC().containsObject(object)
}
func indexOf(#object:AnyObject) -> Int {
return self.bridgeToObjectiveC().indexOfObject(object)
}
mutating func moveObjectAtIndex(fromIndex: Int, toIndex: Int) {
if ((fromIndex == toIndex) || (fromIndex > self.count) ||
(toIndex > self.count)) {
return
}
// Get object being moved so it can be re-inserted
let object = self[fromIndex]
// Remove object from array
self.removeAtIndex(fromIndex)
// Insert object in array at new location
self.insert(object, atIndex: toIndex)
}
}
func delayOnMainQueueFor(numberOfSeconds delay:Double, action closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue()) {
closure()
}
}
In swift, you can create a singleton class following way:
class AppSingleton: NSObject {
//Shared instance of class
static let sharedInstance = AppSingleton()
override init() {
super.init()
}
}
I prefer this implementation:
class APIClient {
}
var sharedAPIClient: APIClient = {
return APIClient()
}()
extension APIClient {
class func sharedClient() -> APIClient {
return sharedAPIClient
}
}
My way of implementation in Swift...
ConfigurationManager.swift
import Foundation
let ConfigurationManagerSharedInstance = ConfigurationManager()
class ConfigurationManager : NSObject {
var globalDic: NSMutableDictionary = NSMutableDictionary()
class var sharedInstance:ConfigurationManager {
return ConfigurationManagerSharedInstance
}
init() {
super.init()
println ("Config Init been Initiated, this will be called only onece irrespective of many calls")
}
Access the globalDic from any screen of the application by the below.
Read:
println(ConfigurationManager.sharedInstance.globalDic)
Write:
ConfigurationManager.sharedInstance.globalDic = tmpDic // tmpDict is any value that to be shared among the application
The only right approach is below.
final class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code if anything
return instance
}()
private init() {}
}
To Access
let signleton = Singleton.sharedInstance
Reasons:
static type property is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously, so no need of using dispatch_once
Privatising the init method so instance can't be created by other classes.
final class as you do not want other classes to inherit Singleton class.
After seeing David's implementation, it seems like there is no need to have a singleton class function instanceMethod since let is doing pretty much the same thing as a sharedInstance class method. All you need to do is declare it as a global constant and that would be it.
let gScopeManagerSharedInstance = ScopeManager()
class ScopeManager {
// No need for a class method to return the shared instance. Use the gScopeManagerSharedInstance directly.
}
func init() -> ClassA {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : ClassA? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = ClassA()
}
return Static.instance!
}
Swift to realize singleton in the past, is nothing more than the three ways: global variables, internal variables and dispatch_once ways.
Here are two good singleton.(note: no matter what kind of writing will must pay attention to the init () method of privatisation.Because in Swift, all the object's constructor default is public, needs to be rewritten init can be turned into private, prevent other objects of this class '()' by default initialization method to create the object.)
Method 1:
class AppManager {
private static let _sharedInstance = AppManager()
class func getSharedInstance() -> AppManager {
return _sharedInstance
}
private init() {} // Privatizing the init method
}
// How to use?
AppManager.getSharedInstance()
Method 2:
class AppManager {
static let sharedInstance = AppManager()
private init() {} // Privatizing the init method
}
// How to use?
AppManager.sharedInstance
Swift 5.2
You can point to the type with Self. So:
static let shared = Self()
And should be inside a type, like:
class SomeTypeWithASingletonInstance {
static let shared = Self()
}
This is the simplest one with thread safe capabilities. No other thread can access the same singleton object even if they want. Swift 3/4
struct DataService {
private static var _instance : DataService?
private init() {} //cannot initialise from outer class
public static var instance : DataService {
get {
if _instance == nil {
DispatchQueue.global().sync(flags: .barrier) {
if _instance == nil {
_instance = DataService()
}
}
}
return _instance!
}
}
}
I required my singleton to allow inheritance, and none of these solutions actually allowed it. So I came up with this:
public class Singleton {
private static var sharedInstanceVar = Singleton()
public class func sharedInstance() -> Singleton {
return sharedInstanceVar
}
}
public class SubSingleton: Singleton {
private static var sharedInstanceToken: dispatch_once_t = 0
public class override func sharedInstance() -> SubSingleton {
dispatch_once(&sharedInstanceToken) {
sharedInstanceVar = SubSingleton()
}
return sharedInstanceVar as! SubSingleton
}
}
This way when doing Singleton.sharedInstance() first it will return the instance of Singleton
When doing SubSingleton.sharedInstance() first it will return the instance of SubSingleton created.
If the above is done, then SubSingleton.sharedInstance() is Singleton is true and the same instance is used.
The issue with this first dirty approach is that I cannot guarantee that subclasses would implement the dispatch_once_t and make sure that sharedInstanceVar is only modified once per class.
I will try to refine this further, but it would be interesting to see if anyone has strong feelings against this (besides the fact that it is verbose and requires to manually update it).
This is my implementation. It also prevents the programmer from creating a new instance:
let TEST = Test()
class Test {
private init() {
// This is a private (!) constructor
}
}
I use the following syntax:
public final class Singleton {
private class func sharedInstance() -> Singleton {
struct Static {
//Singleton instance.
static let sharedInstance = Singleton()
}
return Static.sharedInstance
}
private init() { }
class var instance: Singleton {
return sharedInstance()
}
}
This works from Swift 1.2 up to 4, and has several advantages:
Reminds the user not to subclass implementation
Prevents creation of additional instances
Ensures lazy creation and unique instantiation
Shortens syntax (avoids ()) by allowing to access instance as Singleton.instance

Use of Unresolved Identifier "Singleton."

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

Access static variables within class in Swift

Is ClassName.staticVaribale the only way to access static variable within the class? I want something like self, but for class. Like class.staticVariable.
There are two ways to access a static property/method from a non-static property/method:
As stated in your question, you can prefix the property/method name with that of the type:
class MyClass {
static let staticProperty = 0
func method() {
print(MyClass.staticProperty)
}
}
Swift 2: You can use dynamicType:
class MyClass {
static let staticProperty = 0
func method() {
print(self.dynamicType.staticProperty)
}
}
Swift 3: You can use type(of:) (thanks #Sea Coast of Tibet):
class MyClass {
static let staticProperty = 0
func method() {
print(type(of: self).staticProperty)
}
}
If you're inside a static property/method you do not need to prefix the static property/method with anything:
class MyClass {
static let staticProperty = 0
static func staticMethod() {
print(staticProperty)
}
}
This is solved elegantly in Swift 5.1
you can access it via
Self.yourConstant
Reference: https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
There is a way in Swift to make Marcel's answer satisfy even most picky style-guide gods
class MyClass {
private typealias `Self` = MyClass
static let MyConst = 5
func printConst() {
print(Self.MyConst)
}
}
That makes Self available like in protocols when you want access associated type declaration.
I am not sure about Swift 1 because never tried it but in Swift 2 it works perfectly
In a future Swift 3 version (yet to be released) you can use Self (yes, that's with a capital) to reference to the containing class. A proposal for this was accepted, but the feature is not implemented yet.
For example:
struct CustomStruct {
static func staticMethod() { ... }
func instanceMethod() {
Self.staticMethod() // in the body of the type
}
}
Source: https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md
You could work around this by defining a self referencing typealias.
class MyClassWithALongName {
typealias CLASS = MyClassWithALongName
static let staticFoo = "foo"
func someInstanceMethod() -> String {
return CLASS.staticFoo
}
}
Though the style-guide gods may not approve.
It looks like in Swift 4.2 the inner class and instance variable can directly access the static variable without the prefix of the class name. However, you still need the class name within a function.
class MyClass {
static let staticProperty = 0
let property = staticProperty //YES
class Inner {
func method() {
print(staticProperty) //YES
}
}
func method() {
print(staticProperty) //NO
print(MyClass.staticProperty) //YES
}
}
I don't like the typealias way in this case. My workaround is:
class MyClass {
static let myStaticConst: Int = 1
var myStaticConst:Int {
return type(of: self).myStaticConst
}
func method() {
let i:Int = myStaticConst
}
}

Singleton in Swift

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()