Сінглтон із властивостями в Swift 3


88

У документі Apple Swift з використанням какао та Objective-C (оновленому для Swift 3) Apple наведено такий приклад шаблону Singleton:

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

        // setup code

        return instance
    }()
}

Уявімо, що цей синглтон повинен управляти змінним масивом Рядок. Як / де я повинен оголосити цю властивість і переконатися, що вона належним чином ініціалізується до порожнього [String]масиву?

Відповіді:


236

Для мене це найкращий спосіб, зробити init приватним. Швидкий синтаксис 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
Я підтримав цю відповідь, але, щоб відповідати синтаксису Swift 3, "sharedInstance" слід змінити на просто "shared".
B-Rad

1
Якщо не відбудеться регресії від швидкого 2 до швидкого 3, ви цього не зробите
Тібо Ной

1
Тип після спільного можна опустити, правда? static let shared = Singleton()
chriswillow

1
@YannickSteph, вам не потрібно писати, static let shared: Singleton = Singleton()натомість ви можете просто писатиstatic let shared = Singleton()
chriswillow

3
@RomanN Ні, ви не можете замінити init, оскільки він не успадковує клас. Якщо ви можете це зробити, з цим прикладом final class Singleton: NSObject { private override init() { } }
YannSteph

59

Ви можете ініціалізувати такий порожній масив.

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

Або якщо ви віддаєте перевагу іншому підходу, цей добре підійде.

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

Цей метод не працює в розширенні? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Ендрю

1
Цікаво, що Apple використовує class varв iOS 10 для одиночних (наприклад, UIApplication). Чи буде їх виконання таким самим, як це?
jjatie

2
Я віддаю перевагу одиночним методам init, як privateметодам навіть internal. Це заважає іншим використовувати за замовчуванням ініціалізатор '()' для цього класу.
Kumar C

1
@KumarC Ви маєте рацію, чи не вирішить це проблему, якщо ми додамо privatein init.

@TikhonovAlexander Не могли б Ви надати більше інформації?
Домінік Віал,

30

Відповідно до документації до яблука: у Swift ви можете просто використовувати властивість статичного типу, яке гарантовано буде ліниво ініціалізоване лише один раз, навіть при одночасному доступі до декількох потоків .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

За допомогою методу ініціалізації:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}

3
чому init () не є приватним?
XcodeNOOB

0

Будь-яка ініціалізація здійснюється методом init. Тут немає різниці між одиночним і несінглтонним.


26
Додатковий фрагмент коду, який безпосередньо відповідає на запитання, зробить цю відповідь більш корисною.
Реда Лемеден
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.