Подтвердить что ты не робот

"инициализировать" метод класса для классов в Swift?

Я ищу поведение, подобное методу класса Objective-C +(void)initialize, в котором метод вызывается один раз, когда класс инициализируется и никогда больше не будет после этого.

Простой class init () {} в закрытии class был бы действительно гладким! И, очевидно, когда мы будем использовать "class var s" вместо "static var в закрытии структуры", все это будет хорошо соответствовать!

4b9b3361

Ответ 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)