"инициализировать" метод класса для классов в Swift?
Я ищу поведение, подобное методу класса Objective-C +(void)initialize
, в котором метод вызывается один раз, когда класс инициализируется и никогда больше не будет после этого.
Простой class init () {}
в закрытии class
был бы действительно гладким! И, очевидно, когда мы будем использовать "class var
s" вместо "static var
в закрытии структуры", все это будет хорошо соответствовать!
Ответы
Ответ 1
Если у вас класс Objective-C, проще всего переопределить +initialize
. Однако убедитесь, что подклассы вашего класса также переопределяют +initialize
, иначе ваш класс +initialize
может вызываться более одного раза! Если вы хотите, вы можете использовать dispatch_once()
(упомянутый ниже) для защиты от нескольких вызовов.
class MyView : UIView {
override class func initialize () {
// Do stuff
}
}
Если у вас есть класс Swift, лучшее, что вы можете получить, это dispatch_once()
внутри оператора init()
.
private var once = dispatch_once_t()
class MyObject {
init () {
dispatch_once(&once) {
// Do stuff
}
}
}
Это решение отличается от +initialize
(которое вызывается при первом запуске класса Objective-C) и, следовательно, не является верным ответом на вопрос. Но он работает достаточно хорошо, ИМО.
Ответ 2
В Swift нет инициализатора типа.
"В отличие от хранимых свойств экземпляра вы всегда должны указывать хранимые свойства типа по умолчанию. Это связано с тем, что сам тип не имеет инициализатора, который может присваивать значение сохраненному типу свойства при инициализации время".
Отрывок из: Apple Inc. "Быстрый язык программирования". iBooks.
Вы можете использовать свойство type, значение по умолчанию которого является закрытием. Таким образом, код в закрытии будет выполняться, когда будет установлено свойство type (или переменная класса).
class FirstClass {
class var someProperty = {
// you can init the class member with anything you like or perform any code
return SomeType
}()
}
Но class stored properties not yet supported
(проверено в Xcode 8).
Один ответ заключается в использовании static
, это то же самое, что и class final
.
Хорошая ссылка для этого
Установка значения свойства по умолчанию с закрытием или функцией
Отрывок из: Apple Inc. "Быстрый язык программирования". iBooks.
Пример кода:
class FirstClass {
static let someProperty = {
() -> [Bool] in
var temporaryBoard = [Bool]()
var isBlack = false
for i in 1...8 {
for j in 1...8 {
temporaryBoard.append(isBlack)
isBlack = !isBlack
}
isBlack = !isBlack
}
print("setting default property value with a closure")
return temporaryBoard
}()
}
print("start")
FirstClass.someProperty
Печать
старт
установка значения свойства по умолчанию с закрытием
Итак, он ленивый.
Ответ 3
Для @objc
классов class func initialize()
определенно работает, так как +initialize
реализуется средой Objective-C. Но для "родных" классов Swift вам понадобятся другие ответы.
Ответ 4
@aleclarson прибил его, но с недавнего Swift 4 вы не можете напрямую переопределить initialize
. Вы все еще можете достичь этого с помощью Objective-C и категорий для классов, наследующих от NSObject
с помощью метода class/static swiftyInitialize
, который вызывается из Objective-C в MyClass.m
, который вы включаете в источники компиляции вместе с MyClass.swift
# MyView.swift
import Foundation
public class MyView: UIView
{
@objc public static func swiftyInitialize() {
Swift.print("Rock 'n' roll!")
}
}
# MyView.m
#import "MyProject-Swift.h"
@implementation MyView (private)
+ (void)initialize { [self swiftyInitialize]; }
@end
Если ваш класс не может наследовать от NSObject
, а использование +load
вместо +initialize
подходит для подгонки, вы можете сделать что-то вроде этого:
# MyClass.swift
import Foundation
public class MyClass
{
public static func load() {
Swift.print("Rock 'n' roll!")
}
}
public class MyClassObjC: NSObject
{
@objc public static func swiftyLoad() {
MyClass.load()
}
}
# MyClass.m
#import "MyProject-Swift.h"
@implementation MyClassObjC (private)
+ (void)load { [self swiftyLoad]; }
@end
Есть несколько исправлений, особенно при использовании этого подхода в статических библиотеках, ознакомьтесь с полным post на Medium для деталей! ✌️
Ответ 5
Я не могу найти допустимый пример использования, чтобы иметь что-то вроде +[initialize]
в Swift. Возможно, это объясняет, что этого не существует.
Зачем нам +[initialize]
в ObjC?
Чтобы инициализировать некоторую глобальную переменную
static NSArray *array;
+ (void)initialize {
array = @[1,2,3];
}
который в Swift
struct Foo {
static let array = [1,2,3]
}
Чтобы сделать взломать
+ (void)initialize {
swizzle_methodImplementation()
}
который не поддерживается Swift (я не могу понять, как это сделать для чистого класса Swift/struct/enum)