Ответ 1
dispatch_once_t
- это псевдоним типа (Int
). Документация заголовка:
/*!
* @typedef dispatch_once_t
*
* @abstract
* A predicate for use with dispatch_once(). It must be initialized to zero.
* Note: static and global variables default to zero.
*/
typealias dispatch_once_t = Int
И вот цитата из dispatch_once
документации:
Предикат должен указывать на переменную, хранящуюся в глобальной или статической объем. Результат использования предиката с автоматическим или динамическим хранилище (включая переменные экземпляра Objective-C) undefined.
Переменная токена должна храниться в глобальной/статической области и должна быть инициализирована до нуля, что приводит к этому коду:
import Foundation
var token: dispatch_once_t = 0
dispatch_once(&token) { () -> Void in
print("Called once")
}
Это не работает, если вы опускаете = 0
(token
инициализацию), потому что компилятор дает ошибку Адрес переменной "токен", принятый до его инициализации, несмотря на то, что статика и глобальные значения по умолчанию равны нулю. Протестировано в Xcode 7B2.
Дополнительные примеры на основе комментариев. Если вы находитесь внутри метода class
, у вас есть несколько возможностей.
Вы не можете объявлять статическое свойство внутри метода, иначе компилятор дает Статические свойства могут быть объявлены только при ошибке типа. Это не работает:
class func doItOnce() {
static var token: dispatch_once_t = 0
...
}
Должен быть объявлен по типу. Это было введено в Swift 1.2 (Xcode 6.3 IIRC).
"статические" методы и свойства теперь разрешены в классах (как псевдоним для "final class" ). Теперь вам разрешено объявлять статические данные свойства в классах, которые имеют глобальное хранилище и ленивы инициализируется при первом доступе (например, глобальные переменные). Протоколы сейчас объявлять требования типа как "статические" требования вместо заявляя их как "классные" требования. (17198298)
Итак, что мы можем сделать, если нам не нравятся глобальные переменные?
Статическая переменная типа
class MyClass {
private static var token: dispatch_once_t = 0
class func doItOnce() {
dispatch_once(&token) {
print("Do it once")
}
}
}
Статический метод, заключенный в структуру
Не нравится статическое свойство в классе yur? Хочешь иметь это в своем методе? Оберните его в структуру следующим образом:
class func doItOnce() {
struct Tokens { static var token: dispatch_once_t = 0 }
dispatch_once(&Tokens.token) {
print("Do it once")
}
}
На самом деле я не знаю ни одной рекомендации Apple, лучшей практики... как это сделать для dispatch_once
. Просто используйте то, что вам больше всего нравится, чувствует себя хорошо и просто отвечайте критериям глобальной/статической области.