Korzystanie z modelu singleton once w Swift

Staram się wypracować odpowiedni model Singletona do użycia w Swift. Do tej pory udało mi się uzyskać bezpieczny model bez wątku działający jako:

class var sharedInstance:TPScopeManager {
    get {
        struct Static {
            static var instance : TPScopeManager? = nil
        }

        if !Static.instance {
            Static.instance = TPScopeManager()
        }

        return Static.instance!
    }
}

Owijanie instancji Singletona w statyczną strukturę powinno pozwolić na pojedynczą instancję, która nie koliduje z instancjami Singletona bez skomplikowanych schematów nazewnictwa. Oczywiście ten model nie jest bezpieczny dla wątków, więc próbowałem dodać dispatch_once do całości: {]}

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!
    }
}

Ale Ja błąd kompilatora w linii dispatch_once:

Nie można przekształcić typu wyrażenia "Void" NA typ "() "

Próbowałem kilku różnych wariantów składni, ale wszystkie wydają się mieć te same wyniki:

dispatch_once(Static.token, { Static.instance = TPScopeManager() })

Jakie jest właściwe użycie dispatch_once przy użyciu Swift? Początkowo myślałem, że problem dotyczy bloku z powodu () w komunikacie o błędzie, ale im więcej na niego patrzę, tym bardziej myślę, że może to być kwestia poprawnego zdefiniowania dispatch_once_t.

Author: Forge, 2014-06-04

29 answers

tl; dr: użyj metody stałej klasy , Jeśli używasz kodu Swift 1.2 lub nowszego oraz metody zagnieżdżonej struktury, jeśli potrzebujesz wsparcia dla wcześniejszych wersji.

Z mojego doświadczenia z Swift są trzy podejścia do implementacji wzorca Singletona, które obsługują leniwą inicjalizację i bezpieczeństwo wątków.

Stała klasy

class Singleton  {
   static let sharedInstance = Singleton()
}

To podejście wspiera leniwą inicjalizację, ponieważ Swift leniwie inicjalizuje stałe klas (I zmienne), i jest Bezpieczny przez definicję let. To jest teraz oficjalnie zalecany sposób , aby utworzyć instancję Singletona.

Stałe klas zostały wprowadzone w Swift 1.2. Jeśli chcesz obsługiwać wcześniejszą wersję Swift, użyj zagnieżdżonego podejścia struct poniżej lub stałej globalnej.

Zagnieżdżona struktura

class Singleton {
    class var sharedInstance: Singleton {
        struct Static {
            static let instance: Singleton = Singleton()
        }
        return Static.instance
    }
}

Tutaj używamy stałej statycznej zagnieżdżonej struktury jako stałej klasy. Jest to obejście braku statycznych stałych klas w Swift 1.1 i wcześniej i nadal działa jako obejście braku stałych i zmiennych statycznych w funkcjach.

Dispatch_once

Tradycyjne podejście Objective-C zostało przeniesione na Swift. Jestem prawie pewien, że nie ma żadnej przewagi nad zagnieżdżonym podejściem struct, ale i tak umieszczam go tutaj, ponieważ uważam, że różnice w składni są interesujące.

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!
    }
}

Zobacz ten projekt GitHub dla testów jednostkowych.

 673
Author: hpique,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 05:29:34

Ponieważ Apple wyjaśniło teraz, że statyczne zmienne struct są inicjalizowane zarówno leniwe, jak i zawinięte w dispatch_once( patrz notatka na końcu posta), myślę, że moim ostatecznym rozwiązaniem będzie:

class WithSingleton {
    class var sharedInstance :WithSingleton {
        struct Singleton {
            static let instance = WithSingleton()
        }

        return Singleton.instance
    }
}

To wykorzystuje automatyczną leniwą, bezpieczną dla wątków inicjalizację statycznych elementów struktury, bezpiecznie ukrywa rzeczywistą implementację przed konsumentem, przechowuje wszystko w zwartym podziale dla czytelności i eliminuje widoczną zmienną globalną.

Jabłko wyjaśniono, że Lazy initializer są bezpieczne dla wątków, więc nie ma potrzeby stosowania dispatch_once lub podobnych zabezpieczeń

Leniwy inicjalizator zmiennej globalnej (również dla statycznych członków struktur i enum) jest uruchamiany przy pierwszym dostępie do zmiennej globalnej i jest uruchamiany jako dispatch_once, aby upewnić się, że inicjalizacja jest atomowa. Pozwala to na użycie dispatch_once w kodzie: wystarczy zadeklarować zmienną globalną za pomocą inicjatora i oznaczyć ją jako prywatną.

Od tutaj

 170
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-05 16:08:19

Dla Swift 1.2 i nowszych:

class Singleton  {
   static let sharedInstance = Singleton()
}

Z dowodem poprawności (cała zasługa idzie tutaj ), nie ma powodu, aby używać żadnej z poprzednich metod dla singletonów.

Update : to jest teraz oficjalny sposób definiowania singletonów, jak opisano w official docs!

Jeśli chodzi o obawy dotyczące stosowania static vs class. static powinny być używane nawet wtedy, gdy zmienne class staną się dostępne. Singletony nie są miał być podklasowany, ponieważ skutkowałoby to wieloma instancjami bazowego Singletona. Użycie static wymusza to w piękny, szybki sposób.

Dla Swift 1.0 i 1.1:

W związku z ostatnimi zmianami w Swift, głównie nowymi metodami kontroli dostępu, skłaniam się teraz ku czystszemu sposobowi używania zmiennej globalnej dla singletonów.

private let _singletonInstance = SingletonClass()
class SingletonClass {
  class var sharedInstance: SingletonClass {
    return _singletonInstance
  }
}

Jak wspomniano w artykule Swift blog tutaj :

Leniwy inicjalizator zmiennej globalnej (także dla statycznych członków structs and enums) jest uruchamiany przy pierwszym dostępie do globalnej, a jest uruchamiany jako dispatch_once, aby upewnić się, że inicjalizacja jest atomic. Pozwala to na użycie dispatch_once w kodzie: wystarczy zadeklarować zmienną globalną za pomocą inicjatora i zaznaczyć ją szeregowy.

Ten sposób tworzenia singletonu jest bezpieczny, szybki, leniwy, a także połączony z ObjC za darmo.

 160
Author: Jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-27 16:14:24

Swift 1.2 lub nowszy obsługuje teraz statyczne zmienne/stałe w klasach. Można więc użyć stałej statycznej:

class MySingleton {

    static let sharedMySingleton = MySingleton()

    private init() {
        // ...
    }
}
 45
Author: Florian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 13:18:41

Jest na to lepszy sposób. Możesz zadeklarować zmienną globalną w swojej klasie powyżej declection klasy w ten sposób

var tpScopeManagerSharedInstance = TPScopeManager()

Wywołanie domyślnego init lub dowolnej zmiennej INIT i globalnej dispatch_once domyślnie w języku Swift. Następnie w klasie, którą chcesz uzyskać referencję, po prostu zrób to:

var refrence = tpScopeManagerSharedInstance
// or you can just access properties and call methods directly
tpScopeManagerSharedInstance.someMethod()

Więc w zasadzie można pozbyć się całego bloku współdzielonego kodu instancji.

 32
Author: Kris Gellci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-05 18:02:59

Singletony Swift są eksponowane w frameworkach Cocoa jako funkcje klasowe, np. NSFileManager.defaultManager(), NSNotificationCenter.defaultCenter(), wydaje mi się więc, że bardziej sensowne jest odzwierciedlenie tego zachowania jako funkcji klasy, a nie jako zmiennej klasy, jak używają niektóre inne rozwiązania, np.

class MyClass {

    private static let _sharedInstance = MyClass()

    class func sharedInstance() -> MyClass {
        return _sharedInstance
    }
}

Pobierz singleton przez MyClass.sharedInstance().

 27
Author: Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 08:57:31

Zgodnie z dokumentacją Apple , wielokrotnie powtarzano, że najprostszym sposobem na to jest użycie właściwości statycznych typu:

class Singleton {
    static let sharedInstance = Singleton()
}

Jeśli jednak szukasz sposobu na wykonanie dodatkowej konfiguracji poza prostym wywołaniem konstruktora, sekretem jest użycie natychmiast wywołanego zamknięcia:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()
        // setup code
        return instance
    }()
}

Jest to gwarantowane, że wątek będzie bezpieczny i leniwie zainicjowany tylko raz.

 15
Author: Adrian Macneil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-18 07:31:03

Swift 4+

protocol Singleton: class {
    static var sharedInstance: Self { get }
}

final class Kraken: Singleton {
    static let sharedInstance = Kraken()
    private init() {}
}
 15
Author: Adam Smaka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-12 06:50:46

Patrząc na przykładowy kod Apple ' a natknąłem się na ten wzór. Nie jestem pewien, jak Swift radzi sobie ze statyką, ale to byłoby bezpieczne w C#. I obejmują zarówno właściwość i metodę dla Objective-C interop.

struct StaticRank {
    static let shared = RankMapping()
}

class func sharedInstance() -> RankMapping {
    return StaticRank.shared
}

class var shared:RankMapping {
    return StaticRank.shared
}
 9
Author: user2485100,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 08:52:41

Jeśli planujesz użyć swojej klasy SWIFT singleton w Objective-C, Ta konfiguracja spowoduje, że kompilator wygeneruje odpowiednie nagłówki podobne do Objective-C:

class func sharedStore() -> ImageStore {
struct Static {
    static let instance : ImageStore = ImageStore()
    }
    return Static.instance
}

Wtedy w klasie Objective-C możesz nazywać swój singleton tak, jak zrobiłeś to w przedświątecznych dniach:

[ImageStore sharedStore];
To tylko moja prosta realizacja.
 5
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-15 16:28:40

Pierwsze rozwiązanie

let SocketManager = SocketManagerSingleton();

class SocketManagerSingleton {

}

Później w kodzie:

func someFunction() {        
    var socketManager = SocketManager        
}

Drugie rozwiązanie

func SocketManager() -> SocketManagerSingleton {
    return _SocketManager
}
let _SocketManager = SocketManagerSingleton();

class SocketManagerSingleton {

}

A później w Twoim kodzie będziesz mógł zachować szelki dla mniej zamieszania:

func someFunction() {        
    var socketManager = SocketManager()        
}
 5
Author: Nicolas Manzini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 22:47:59

Użycie:

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!
        }
    }
}

Jak używać:

UtilSingleton.shareInstance.iVal++
println("singleton new iVal = \(UtilSingleton.shareInstance.iVal)")
 5
Author: Kingiol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 08:54:26

W skrócie,

class Manager {
    static let sharedInstance = Manager()
    private init() {}
}

Możesz przeczytać Pliki i inicjalizację

Leniwy inicjalizator zmiennej globalnej (także dla statycznych członków structs and enums) jest uruchamiany przy pierwszym dostępie do globalnej, a jest uruchamiany jako dispatch_once, aby upewnić się, że inicjalizacja jest atomic.

 4
Author: onmyway133,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 11:02:23
final class MySingleton {
     private init() {}
     static let shared = MySingleton()
}

To zadzwoń;

let shared = MySingleton.shared
 4
Author: Kemal Can Kaynak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 12:26:47

Sugerowałbym Enum, jak byś użył w Javie, np.:

enum SharedTPScopeManager: TPScopeManager {
  case Singleton
}
 3
Author: Howard Lovatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 00:56:52

Dla przypomnienia, oto przykładowa implementacja Singletona zagnieżdżonej implementacji struktury Jacka Wu / hpique. Implementacja pokazuje również, jak może działać Archiwizacja, a także niektóre funkcje towarzyszące. Nie mogłem znaleźć tego pełnego przykładu, więc mam nadzieję, że to komuś pomoże!

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

I jeśli nie rozpoznałeś niektórych z tych funkcji, oto mały żywy plik narzędziowy Swift, którego używałem:

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()
    }
}
 3
Author: SchoonSauce,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-26 20:04:02

Najlepsze podejście w Swift powyżej 1.2 to jednowierszowy singleton, as -

class Shared: NSObject {

    static let sharedInstance = Shared()

    private override init() { }
}

Aby dowiedzieć się więcej o tym podejściu, możesz odwiedzić ten link .

 3
Author: CodeCracker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 09:00:31

Wolę tę implementację:

class APIClient {

}

var sharedAPIClient: APIClient = {
    return APIClient()
}()

extension APIClient {
    class func sharedClient() -> APIClient {
        return sharedAPIClient
    }
}
 2
Author: Viktor Radchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-11 23:23:16

Mój sposób implementacji w 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")   

}

Dostęp do globalDic z dowolnego ekranu aplikacji przez Poniżej.

Powinno być:

 println(ConfigurationManager.sharedInstance.globalDic)  

Napisz:

 ConfigurationManager.sharedInstance.globalDic = tmpDic // tmpDict is any value that to be shared among the application
 2
Author: user2737730,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 09:57:24

Z Apple Docs (Swift 3.0.1),

Można po prostu użyć właściwości static type, która jest gwarantowana leniwie zainicjowany tylko raz, nawet gdy dostęp do wielu wątki jednocześnie:

class Singleton {
    static let sharedInstance = Singleton()
}

Jeśli potrzebujesz wykonać dodatkową konfigurację poza inicjalizacją, możesz przypisanie wyniku wywołania zamknięcia do globalnego stała:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()
        // setup code
        return instance
    }()
}
 2
Author: sleepwalkerfx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-20 04:58:51

Po obejrzeniu implementacji Davida, wydaje się, że nie ma potrzeby posiadania funkcji klasy singleton instanceMethod, ponieważ let robi prawie to samo, co metoda klasy sharedInstance. Wszystko, co musisz zrobić, to zadeklarować ją jako stałą globalną i to by było na tyle.

let gScopeManagerSharedInstance = ScopeManager()

class ScopeManager {
 // No need for a class method to return the shared instance. Use the gScopeManagerSharedInstance directly. 
}
 2
Author: Essa A. Haddad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 08:55:20
   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!
}
 1
Author: DD.amor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 07:44:38

Właśnie się na to natknąłem, ale wymagałem mojego Singletona, aby pozwolił na dziedziczenie, a żadne z tych rozwiązań nie pozwalało na to.

Więc wymyśliłem to:

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
  }
}
    W ten sposób wykonując Singleton.sharedInstance () najpierw zwróci instancję Singleton
  • podczas wykonywania SubSingleton.sharedInstance () najpierw zwróci instancję utworzonego Subsingletona.
  • Jeśli powyższe jest zrobione, to SubSingleton.sharedInstance () is Singleton is true and the ta sama instancja jest używana.

Problem z tym pierwszym brudnym podejściem polega na tym, że nie mogę zagwarantować, że podklasy zaimplementują dispatch_once_t i upewnią się, że sharedInstanceVar jest modyfikowany tylko raz na klasę...

Postaram się dopracować to dalej, ale interesujące byłoby zobaczyć, czy ktoś ma silne uczucia przeciwko temu (poza tym, że jest gadatliwy i wymaga ręcznej aktualizacji).

 0
Author: RicardoDuarte,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-10 08:59:34

Jest to najprostszy z możliwościami bezpiecznego wątku. Żaden inny wątek nie może uzyskać dostępu do tego samego obiektu singleton, nawet jeśli chce. 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!
        }
    }
}
 0
Author: Abhishek Biswas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 12:32:41

Swift do zrealizowania Singletona w przeszłości, to nic innego jak trzy sposoby: zmienne globalne, zmienne wewnętrzne i sposoby dispatch_once.

Oto dwa dobre singleton.(uwaga: bez względu na to, jakiego rodzaju pismo będzie zwracać uwagę na metodę INIT () prywatyzacji.Ponieważ w Swift wszystkie obiekty konstruktora default są publiczne, trzeba je przepisać init może być zamieniony na prywatny, domyślnie uniemożliwia innym obiektom tej klasy '()' utworzenie domyślnej metody inicjalizacji obiekt.)

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

Metoda 2:

class AppManager {
    static let sharedInstance = AppManager()

    private init() {} // Privatizing the init method
}

// How to use?
AppManager.sharedInstance
 0
Author: Steven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-03 07:19:26

To moja realizacja. Uniemożliwia to również programiście tworzenie nowej instancji:

let TEST = Test()

class Test {

    private init() {
        // This is a private (!) constructor
    }
}
 -1
Author: Yedidya Reiss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 18:28:04
private var sharedURLCacheForRequestsKey:Void?
extension URLCache{
public static func sharedURLCacheForRequests()->URLCache{
    var cache = objc_getAssociatedObject(OperationQueue.main, &sharedURLCacheForRequestsKey)
    if cache is URLCache {

    }else{
        cache = URLCache(memoryCapacity: 0, diskCapacity: 1*1024*1024*1024, diskPath: "sharedURLCacheForRequestsKey")
        objc_setAssociatedObject(OperationQueue.main, &sharedURLCacheForRequestsKey, cache, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

    }
    return cache as! URLCache
}}
 -1
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 09:28:15

Zwykle używam następującej składni jako najbardziej kompletnej:

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()
    }
}
To działa od Swift 1.2 do 4 i oferuje kilka zalet:]}
  1. przypomina użytkownikowi, aby nie podklasował implementacji
  2. zapobiega tworzeniu dodatkowych instancji
  3. zapewnia leniwe tworzenie i unikalną instancję
  4. skraca składnię (avoids ()) pozwalając na dostęp do instancji jako Singleton.instance
 -1
Author: Gonzalo Durañona,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-21 01:44:08

Użyj statycznej zmiennej i prywatnego inicjatora, aby utworzyć klasę singleton.

class MySingletonClass {

    static let sharedSingleton = MySingletonClass()

    private init() {}
}
 -1
Author: Prashant Bhayani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-19 07:59:23