I am writing a custom image fetcher to fetch the images needed for my collection view. Below is my image fetcher logic
class ImageFetcher {
/// Thread safe cache that stores `UIImage`s against corresponding URL's
private var cache = Synchronised([URL: UIImage]())
/// Inflight Requests holder which we can use to cancel the requests if needed
/// Thread safe
private var inFlightRequests = Synchronised([UUID: URLSessionDataTask]())
func fetchImage(using url: URL, completion: #escaping (Result<UIImage, Error>) -> Void) -> UUID? {
/// If the image is present in cache return it
if let image = cache.value[url] {
completion(.success(image))
}
let uuid = UUID()
let dataTask = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
guard let self = self else { return }
defer {
self.inFlightRequests.value.removeValue(forKey:uuid )
}
if let data = data, let image = UIImage(data: data) {
self.cache.value[url] = image
DispatchQueue.main.async {
completion(.success(image))
}
return
}
guard let error = error else {
// no error , no data
// trigger some special error
return
}
// Task cancelled do not send error code
guard (error as NSError).code == NSURLErrorCancelled else {
completion(.failure(error))
return
}
}
dataTask.resume()
self.inFlightRequests.value[uuid] = dataTask
return uuid
}
func cancelLoad(_ uuid: UUID) {
self.inFlightRequests.value[uuid]?.cancel()
self.inFlightRequests.value.removeValue(forKey: uuid)
}
}
This is a block of code that provides the thread safety needed to access the cache
/// Use to make a struct thread safe
public class Synchronised<T> {
private var _value: T
private let queue = DispatchQueue(label: "com.sync", qos: .userInitiated, attributes: .concurrent)
public init(_ value: T) {
_value = value
}
public var value: T {
get {
return queue.sync { _value }
}
set { queue.async(flags: .barrier) { self._value = newValue }}
}
}
I am not seeing the desired scroll performance and I anticipate that is because my main thread is getting blocked when I try to access the cache(queue.sync { _value }). I am calling the fetchImage method from the cellForRowAt method of the collectionView and I can't seem to find a way to dispatch it off the main thread because I would need the request's UUID so I would be able to cancel the request if needed. Any suggestions on how to get this off the main thread or are there any suggestions to architect this in a better way?
I do not believe that your scroll performance is related to fetchImage. While there are modest performance issues in Synchronized, it likely is not enough to explain your issues. That having been said, there are several issue here, but blocking the main queue does not appear to be one of them.
The more likely culprit might be retrieving assets that are larger than the image view (e.g. large asset in small image view requires resizing which can block the main thread) or some mistake in the fetching logic. When you say “not seeing desired scroll performance”, is it stuttering or just slow? The nature of the “scroll performance” problem will dictate the solution.
A few unrelated observations:
Synchronised, used with a dictionary, is not thread-safe. Yes, the getter and setter for value is synchronized, but not the subsequent manipulation of that dictionary. It is also very inefficient (though, not likely sufficiently inefficient to explain the problems you are having).
I would suggest not synchronizing the retrieval and setting of the whole dictionary, but rather make a synchronized dictionary type:
public class SynchronisedDictionary<Key: Hashable, Value> {
private var _value: [Key: Value]
private let queue = DispatchQueue(label: "com.sync", qos: .userInitiated, attributes: .concurrent)
public init(_ value: [Key: Value] = [:]) {
_value = value
}
// you don't need/want this
//
// public var value: [Key: Value] {
// get { queue.sync { _value } }
// set { queue.async(flags: .barrier) { self._value = newValue } }
// }
subscript(key: Key) -> Value? {
get { queue.sync { _value[key] } }
set { queue.async(flags: .barrier) { self._value[key] = newValue } }
}
var count: Int { queue.sync { _value.count } }
}
In my tests, in release build this was about 20 times faster. Plus it is thread-safe.
But, the idea is that you should not expose the underlying dictionary, but rather just expose whatever interface you need for the synchronization type to manage the dictionary. You will likely want to add additional methods to the above (e.g. removeAll or whatever), but the above should be sufficient for your immediate purposes. And you should be able to do things like:
var dictionary = SynchronizedDictionary<String, UIImage>()
dictionary["foo"] = image
imageView.image = dictionary["foo"]
print(dictionary.count)
Alternatively, you could just dispatch all updates to the dictionary to the main queue (see point 4 below), then you don't need this synchronized dictionary type at all.
You might consider using NSCache, instead of your own dictionary, to hold the images. You want to make sure that you respond to memory pressure (emptying the cache) or some fixed total cost limit. Plus, NSCache is already thread-safe.
In fetchImage, you have several paths of execution where you do not call the completion handler. As a matter of convention, you will want to ensure that the completion handler is always called. E.g. what if the caller started a spinner before fetching the image, and stopping it in the completion handler? If you might not call the completion handler, then the spinner might never stop, either.
Similarly, where you do call the completion handler, you do not always dispatch it back to the main queue. I would either always dispatch back to the main queue (relieving the caller from having to do so) or just call the completion handler from the current queue, but only dispatching some of them to the main queue is an invitation for confusion.
FWIW, you can create Unit Tests target and demonstrate the difference between the original Synchronised and the SynchronisedDictionary, by testing a massively concurrent modification of the dictionary with concurrentPerform:
// this is not thread-safe if T is mutable
public class Synchronised<T> {
private var _value: T
private let queue = DispatchQueue(label: "com.sync", qos: .userInitiated, attributes: .concurrent)
public init(_ value: T) {
_value = value
}
public var value: T {
get { queue.sync { _value } }
set { queue.async(flags: .barrier) { self._value = newValue }}
}
}
// this is thread-safe dictionary ... assuming `Value` is not mutable reference type
public class SynchronisedDictionary<Key: Hashable, Value> {
private var _value: [Key: Value]
private let queue = DispatchQueue(label: "com.sync", qos: .userInitiated, attributes: .concurrent)
public init(_ value: [Key: Value] = [:]) {
_value = value
}
subscript(key: Key) -> Value? {
get { queue.sync { _value[key] } }
set { queue.async(flags: .barrier) { self._value[key] = newValue } }
}
var count: Int { queue.sync { _value.count } }
}
class SynchronisedTests: XCTestCase {
let iterations = 10_000
func testSynchronised() throws {
let dictionary = Synchronised([String: Int]())
DispatchQueue.concurrentPerform(iterations: iterations) { i in
let key = "\(i)"
dictionary.value[key] = i
}
XCTAssertEqual(iterations, dictionary.value.count) // XCTAssertEqual failed: ("10000") is not equal to ("834")
}
func testSynchronisedDictionary() throws {
let dictionary = SynchronisedDictionary<String, Int>()
DispatchQueue.concurrentPerform(iterations: iterations) { i in
let key = "\(i)"
dictionary[key] = i
}
XCTAssertEqual(iterations, dictionary.count) // success
}
}
Let's say, there is a variable that I want to make thread safe. One of the most common ways to do this:
var value: A {
get { return queue.sync { self._value } }
set { queue.sync { self._value = newValue } }
}
However, this property is not completely thread safe if we change the value as in the example below:
Class.value += 1
So my question is: Using NSLock on the same principle is also not completely thread safe?
var value: A {
get {
lock.lock()
defer { lock.unlock() }
return self._value
}
set {
lock.lock()
defer { lock.unlock() }
self._value = newValue
}
}
In answer to your question, the lock approach suffers the exact same problems that the GCD approach does. Atomic accessor methods simply are insufficient to ensure broader thread-safety.
The issue is, as discussed elsewhere, that the innocuous += operator is retrieving the value via the getter, incrementing that value, and storing that new value via the setter. To achieve thread-safety, the whole process needs to be wrapped in a single synchronization mechanism. You want an atomic increment operation, you would write a method to do that.
So, taking your NSLock example, I might move the synchronization logic into its own method, e.g.:
class Foo<T> {
private let lock = NSLock()
private var _value: T
init(value: T) {
_value = value
}
var value: T {
get { lock.synchronized { _value } }
set { lock.synchronized { _value = newValue } }
}
}
extension NSLocking {
func synchronized<T>(block: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try block()
}
}
But if you wanted to have an operation to increment the value in a thread-safe manner, you would write a method to do that, e.g.:
extension Foo where T: Numeric {
func increment(by increment: T) {
lock.synchronized {
_value += increment
}
}
}
Then, rather than this non-thread-safe attempt:
foo.value += 1
You would instead employ the following thread-safe rendition:
foo.increment(by: 1)
This pattern, of wrapping the increment process in its own method that synchronizes the whole operation, would be applicable regardless of what synchronization mechanism you use (e.g., locks, GCD serial queue, reader-writer pattern, os_unfair_lock, etc.).
For what it is worth, the Swift 5.5 actor pattern (outlined in SE-0306) formalizes this pattern. Consider:
actor Bar<T> {
var value: T
init(value: T) {
self.value = value
}
}
extension Bar where T: Numeric {
func increment(by increment: T) {
value += increment
}
}
Here, the increment method is automatically an “actor-isolated” method (i.e., it will be synchronized) but the actor will control interaction with the setter for its property, namely if you try to set value from outside this class, you will receive an error:
Actor-isolated property 'value' can only be mutated from inside the actor
That's interesting, I'm learning about this for the first time.
The issue in the first bit of code, is that:
object.value += 1
has the same semantics as
object.value = object.value + 1
which we can further expand to:
let originalValue = queue.sync { object._value }
let newValue = origiinalValue + 1
queue.sync { self._value = newValue }
Expanding it so makes it clear that the synchronization of the getter and setter work fine, but they're not synchronized as a whole. A context switch in the middle of the code above could cause _value to be mutated by another thread, without newValue reflecting the change.
Using a lock would have the exact same problem. It would expand to:
lock.lock()
let originalValue = object._value
lock.unlock()
let newValue = originalValue + 1
lock.lock()
object._value = newValue
lock.unlock()
You can see this for yourself by instrumenting your code with some logging statements, which show that the mutation isn't fully covered by the lock:
class C {
var lock = NSLock()
var _value: Int
var value: Int {
get {
print("value.get start")
print("lock.lock()")
lock.lock()
defer {
print("lock.unlock()")
lock.unlock()
print("value.get end")
}
print("getting self._value")
return self._value
}
set {
print("\n\n\nvalue.set start")
lock.lock()
print("lock.lock()")
defer {
print("lock.unlock()")
lock.unlock()
print("value.set end")
}
print("setting self._value")
self._value = newValue
}
}
init(_ value: Int) { self._value = value }
}
let object = C(0)
object.value += 1
I have an array of 'updateBlocks' (closures) that I use in a singleton class to notify any observers (UIViewControllers, etc) when data updates.
I am wondering what the best way to remove the observer would be so that it is not executed when the observer is deallocated (or no longer wants updates).
Here is my current setup:
MySingleton Class
var updateBlock: (() -> ())? {
didSet {
self.updateBlocks.append(updateBlock!)
self.updateBlock!() // Call immediately to give initial data
}
}
var updateBlocks = [() -> ()]()
func executeUpdateBlocks() {
for block in updateBlocks {
block()
}
}
MyObserver Class
MySingleton.shared.updateBlock = {
...handle updated data...
}
MySingleton.shared.updateBlock = nil // How to properly remove???
Your singleton design has some problems.
Having updateBlock be a variable who's didSet method appends a block to your updateBlocks array is bad design.
I would suggest getting rid of the updateBlock var, and instead defining an addUpdateBlock method and a removeAllUpdateBlocks method:
func addUpdateBlock(_ block () -> ()) {
updateBlocks.append(block)
}
func removeAllUpdateBlocks() {
updateBlocks.removeAll()
}
func executeUpdateBlocks() {
for block in updateBlocks {
block()
}
}
If you want to remove single blocks then you'll need some way to keep track of them. As rmaddy says, you would need some sort of ID for each block. You could refactor your container for your blocks to be a dictionary and use sequential integer keys. When you add a new block, your addBlock function could return the key:
var updateBlocks = [Int: () -> ()]()
var nextBlockID: Int = 0
func addUpdateBlock(_ block () -> ()) -> Int {
updateBlocks[nextBlockID] = block
let result = nextBlockID
nextBlockID += 1
//Return the block ID of the newly added block
return result
}
func removeAllUpdateBlocks() {
updateBlocks.removeAll()
}
func removeBlock(id: Int) -> Bool {
if updateBlocks[id] == nil {
return false
} else {
updateBlocks[id] = nil
return true
}
func executeUpdateBlocks() {
for (_, block) in updateBlocks {
block()
}
If you save your blocks in a dictionary then they won't be executed in any defined order.
That's a very confusing API. From the client's point of view you are setting the value of a single block. But the implementation actually adds that block to an array and then immediately calls that block. And why would you force-unwrap the optional block?
Since you want to support several observers and provide the ability to remove observers, you really show have addBlock and removeBlock methods in your singleton. Then the API and its functionality are clear.
The trick is how to provide an API that lets an observer tell the singleton to remove a specific block. I would model the API after how it is done in the NotificationCenter class where the addBlock method returns some generated token. That token is then passed to the removeBlock method.
The implementation would likely be a dictionary keyed on the token and the value is the block. The token can be a UUID or some other generated, unique opaque value. That makes the addBlock and removeBlock methods simple. Then the executeBlocks method would iterate the values of the dictionary and call those blocks.
Here's one possible implementation:
class UpdateBlocks {
static let shared = UpdateBlocks()
var blocks = [UUID: () -> ()]()
private init() {
}
func addBlock(_ block: #escaping () -> ()) -> Any {
let token = UUID()
blocks[token] = block
return token
}
func removeBlock(_ token: Any) {
if let token = token as? UUID {
blocks[token] = nil
}
}
func executeBlocks() {
for (_, value) in blocks {
value()
}
}
}
let token = UpdateBlocks.shared.addBlock {
print("hello")
}
UpdateBlocks.shared.executeBlocks() // Outputs "hello"
UpdateBlocks.shared.removeBlock(token)
UpdateBlocks.shared.executeBlocks() // No output
In Swift I have this Singleton
struct Networking {
static let shared = Networking()
private var observed: Set<String> = []
}
I have to manipulate observed and I need to create useful method to insert and remove member in Set.
mutating func addObserver(for member: String) {
//other code
observed.insert(member)
}
mutating func removeObserver(for member: String) {
//other code
observed.remove(member)
}
The problem is when I try to call this methods like this
Networking.shared.addObserver(for: "x")
because I'm getting this error
cannot use mutating on immutable value: “shared” is a “let” constant
This error is pretty clear. shared is let and obviously it cannot be modified. But to modify the var I need to declare method as mutating. It's a vicious circle.
Any ideas?
Thanks.
If you want your Networking object to act as a singleton, why not make it a class instead of a struct?
class Networking {
static let shared = Networking()
private var observed: Set<String> = []
func addObserver(for member: String) {
//other code
observed.insert(member)
}
func removeObserver(for member: String) {
//other code
observed.remove(member)
}
}
Networking.shared.addObserver(for: "x")
This simplifies the code and solves your issue.
Basically your syntax is wrong, Networking() creates a new instance of the class.
To use the struct as singleton you have to write
Networking.shared.addObserver(for: "x")
Then declare shared as mutable
static var shared = Networking()
There is also another way of doing it
class Networking {
static let shared = Networking()
var observed: Set<String> = [] {
didSet {
print("set has changed")
}
}
}
Value Type
Since Set is a struct (a value type), the didSet block will be executed every time you add or remove and element to Set.
Networking.shared.observed.insert("a")
set has changed
Networking.shared.observed.insert("b")
set has changed
Networking.shared.observed.remove("a")
set has changed
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