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


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

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

5 60

5 ответов:

если у вас есть класс Objective-C, проще всего просто переопределить +initialize. Однако, убедитесь подклассы свой класс и переопределить +initialize или может быть вызван несколько раз! Если вы хотите, вы можете использовать dispatch_once() (упомянутый ниже) для защиты от нескольких вызовов.

class MyView : UIView {
  override class func initialize () {
    // Do stuff
  }
}

если у вас есть быстрый класс, лучшее, что вы можете получить это dispatch_once() внутри init() заявление.

private var once = dispatch_once_t()

class MyObject {
  init () {
    dispatch_once(&once) {
      // Do stuff
    }
  }
}

этот решение отличается от +initialize (который вызывается в первый раз, когда класс Objective-C отправляется) и, следовательно, не является истинным ответом на вопрос. Но это работает достаточно хорошо, ИМО.

нет инициализатор типа в Swift.

" В отличие от сохраненных свойств экземпляра, вы всегда должны давать сохраненным свойствам типа значение по умолчанию. Это потому что сам тип не имеет инициализатора который может присвоить значение сохраненному свойству типа во время инициализации."

Отрывок Из: Apple Inc. "Язык Программирования Swift."iBooks.


вы могли бы использовать а вид имущества какое значение по умолчанию является закрытием. Таким образом, код в закрытии будет выполнен, когда вид имущества (или переменная класса) устанавливается.

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. "Этот Язык Программирования Swift."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

печать

start

установка значения свойства по умолчанию с закрытием

так это лениво оценивается.

на @objc классов, class func initialize() наверняка работает, так как +initialize реализуется средой выполнения Objective-C. Но для "родных" классов Swift вам придется увидеть другие ответы.

@aleclarson прибил его, но с недавнего Swift 4 Вы не можете напрямую переопределить initialize. Вы все еще можете достичь этого с помощью Objective-C и категорий для классов, наследующих от NSObject С классом / 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

есть несколько gotchas, особенно при использовании этого подхода в статических библиотеках, проверьте полный post на средстве для деталей! ✌️

Я не могу найти ни одного допустимого варианта использования, чтобы иметь что-то вроде +[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 class/struct/enum)