在Swift中"初始化"类的类方法?

ale*_*son 73 ios swift

我正在寻找类似于Objective-C的+(void)initialize类方法的行为,因为该方法在初始化类时被调用一次,之后再也不会被调用.

一个简单class init () {}class关闭将是非常时尚!显然,当我们在结构封闭中使用" class vars"而不是" static vars"时,这一切都将很好地匹配!

ale*_*son 62

如果你有一个Objective-C类,那么最简单的就是覆盖它+initialize.但是,请确保您的类的类也会覆盖+initialize,否则您的类+initialize可能会被多次调用!如果需要,您可以使用dispatch_once()(如下所述)防止多次通话.

class MyView : UIView {
  override class func initialize () {
    // Do stuff
  }
}
Run Code Online (Sandbox Code Playgroud)

 

如果你有一个Swift类,你可以获得的最好的是dispatch_once()init()语句中.

private var once = dispatch_once_t()

class MyObject {
  init () {
    dispatch_once(&once) {
      // Do stuff
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案不同于+initialize(这是第一次发布一个Objective-C类的消息),因此不是问题的真正答案.但它足够好,IMO.

  • 从Swift 3.1(Xcode 8.3)开始,使用`override class func initialize()`现在会生成一个警告,包括"......不保证Swift会调用它,并且在将来的版本中将不允许这样做".请参阅:http://stackoverflow.com/questions/42824541/swift-3-1-deprecates-initialize-how-can-i-achieve-the-same-thing (6认同)
  • 从Swift 4开始,使用`override class func initialize()`是一个错误。 (3认同)
  • @BryanChen为什么?在Objective C中,`initialize`保证只被调用一次.这改变了吗? (2认同)
  • 这与Objective-C中的`+ initialize`不同.Objective-C中的`+ initialize`是第一次*class*是*messaged*.这是在第一次创建类的实例时调用的. (2认同)

Bin*_*ian 51

Swift中没有类型初始值设定项.

"与存储的实例属性不同,您必须始终为存储的类型属性提供默认值.这是因为类型本身没有初始化程序,可以在初始化时为存储的类型属性赋值."

摘录自:Apple Inc."The Swift Programming Language." iBooks.


您可以使用默认值为闭包的type属性.因此,当设置type属性(或类变量)时,将执行闭包中的代码.

class FirstClass {
    class var someProperty = {
     // you can init the class member with anything you like or perform any code
        return SomeType
    }()
}
Run Code Online (Sandbox Code Playgroud)

但是class stored properties not yet supported(在Xcode 8中测试过).

一个答案是使用static,它是一样的class final.

对此有好的联系

使用闭包或函数设置默认属性值

摘录自:Apple Inc."The Swift Programming Language." 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
Run Code Online (Sandbox Code Playgroud)

打印

开始

使用闭包设置默认属性值

所以它是懒惰的评估.

  • Apple表示他们将在未来更新 (3认同)

new*_*cct 7

对于@objc类,class func initialize()确实有效,因为它+initialize是由Objective-C运行时实现的.但对于"原生"Swift课程,你必须看到其他答案.


Cy-*_*4AH 6

您可以使用存储类型属性而不是initialize方法。

class SomeClass: {
  private static let initializer: Void = {
    //some initialization
  }()
}
Run Code Online (Sandbox Code Playgroud)

但是由于存储类型属性实际上是在第一次访问时延迟初始化的,因此您需要在某处引用它们。你可以用普通的存储属性来做到这一点:

class SomeClass: {
  private static let initializer: Void = {
    //some initialization
  }()
  private let initializer: Void = SomeClass.initializer
}
Run Code Online (Sandbox Code Playgroud)

  • @Aquajet:“初始化器”不是计算属性,因为分配的闭包实际上是执行的。请注意末尾的等号和括号。正如答案中提到的,静态属性是惰性评估的,因此在加载类时不会立即执行闭包。相反,它是通过在代码中其他位置引用该属性来触发的。 (3认同)