Singleton com propriedades em Swift 3


88

No documento Using Swift with Cocoa e Objective-C da Apple (atualizado para o Swift 3), eles fornecem o seguinte exemplo do padrão Singleton:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()

        // setup code

        return instance
    }()
}

Vamos imaginar que este singleton precisa gerenciar um array variável de Strings. Como / onde eu declararia essa propriedade e garantir que ela seja inicializada corretamente em uma [String]matriz vazia ?

Respostas:


236

Para mim, esta é a melhor maneira, tornar o init privado. Sintaxe Swift 3 \ 4 \ 5

// MARK: - Singleton

final class Singleton {

    // Can't init is singleton
    private init() { }

    // MARK: Shared Instance

    static let shared = Singleton()

    // MARK: Local Variable

    var emptyStringArray = [String]()

}

4
Eu votei a favor dessa resposta, mas para corresponder à sintaxe do Swift 3, "sharedInstance" deve ser alterado para apenas "shared".
B-Rad de

1
A menos que haja uma regressão de swift 2 para swift 3, você não
thibaut noah

1
O tipo depois de compartilhado pode ser omitido, certo? static let shared = Singleton()
chriswillow,

1
@YannickSteph, você não precisa escrever, static let shared: Singleton = Singleton()basta escreverstatic let shared = Singleton()
chriswillow

3
@RomanN Não, você não pode sobrescrever o init porque ele não herda uma classe. Se você pode fazer isso, com este exemplo final class Singleton: NSObject { private override init() { } }
YannSteph

59

Você pode inicializar um array vazio como este.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton(array: [])
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]

    //MARK: Init

    init( array : [String]) {
        emptyStringArray = array
    }
}

Ou se você preferir uma abordagem diferente, esta será adequada.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton()
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]? = nil

    //MARK: Init

    convenience init() {
        self.init(array : [])
    }

    //MARK: Init Array

    init( array : [String]) {
        emptyStringArray = array
    }
}

Este método não funciona em uma extensão? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andy

1
Interessante que a Apple usa class varno iOS 10 para singletons (por exemplo, UIApplication). A implementação deles seria igual a esta?
jjatie

2
Eu prefiro métodos de inicialização singleton como privatemétodos nem mesmo internal. Isso evita que outros usem o inicializador padrão '()' para esta classe.
Kumar C

1
@KumarC Você está correto, não resolveria o problema se adicionarmos um privateem init.

@TikhonovAlexander Você poderia trazer mais informações?
Dominique Vial

30

De acordo com a documentação da apple: No Swift, você pode simplesmente usar uma propriedade de tipo estático, que tem a garantia de ser inicializada lentamente apenas uma vez, mesmo quando acessada através de vários threads simultaneamente .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

Com método de inicialização:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}

3
porque o init () não é privado?
XcodeNOOB de

0

Qualquer inicialização seria feita em um método init. Nenhuma diferença aqui entre um singleton e um não singleton.


26
Um trecho de código adicional que responde diretamente à pergunta tornaria essa resposta mais útil.
Reda Lemeden
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.