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

时间:2014-06-10 09:16:43

标签: ios swift

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

class init () {}封闭中的简单class非常流畅!显然,当我们在结构闭包中使用“class var s”而不是“static var s”时,这一切都非常匹配!

6 个答案:

答案 0 :(得分:60)

如果你有一个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类的消息),因此不是该问题的真实答案。但它足够好,IMO。

答案 1 :(得分:51)

Swift中没有类型初始化程序

  

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

摘自:Apple Inc.“The Swift Programming Language。”iBooks


您可以使用类型属性,其默认值为闭包。因此,当设置 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.“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

打印

  

启动

     

使用闭包设置默认属性值

所以这是懒惰的评估。

答案 2 :(得分:7)

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

答案 3 :(得分:1)

@aleclarson钉了它,但是从最近的Swift 4开始,你无法直接覆盖initialize。您仍然可以使用Objective-C和继承自NSObject的类的类别以及类/静态swiftyInitialize方法实现它,该方法是从MyClass.m中的Objective-C调用的,您在其中包含与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

有一些问题,特别是在静态库中使用此方法时,请查看Medium上的完整post以获取详细信息! ✌️

答案 4 :(得分:1)

您可以使用存储的类型属性代替initialize方法。

class SomeClass: {
  private static let initializer: Void = {
    //some initialization
  }()
}

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

class SomeClass: {
  private static let initializer: Void = {
    //some initialization
  }()
  private let initializer: Void = SomeClass.initializer
}

答案 5 :(得分:-5)

我找不到任何有效的用例来在Swift中使用+[initialize]之类的东西。也许这解释了它不存在的方式

为什么我们在ObjC中需要+[initialize]

初始化一些全局变量

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做到这一点)