+(void)initialize
类方法的行为,该方法在类初始化时调用一次,之后再也不会调用。在
class
闭包中使用一个简单的class init () {}
会非常简洁!当我们使用"class var
"而不是"static var
在结构体闭包"时,这一切都将非常匹配!如果您拥有一个Objective-C类,最简单的方法是覆盖+initialize
。但是,请确保您的类的子类也重写了+initialize
,否则您的类的+initialize
可能会被调用多次!如果需要,可以使用dispatch_once()
(下面会提到)来防止多次调用。
class MyView : UIView {
override class func initialize () {
// Do stuff
}
}
如果你有一个Swift类,最好的选择是在init()
语句中使用dispatch_once()
函数。
private var once = dispatch_once_t()
class MyObject {
init () {
dispatch_once(&once) {
// Do stuff
}
}
}
这种解决方案与+initialize
(该方法在Objective-C类第一次接收消息时调用)不同,因此并不是对问题的真正答案。但在我看来,它已经足够好了。
在 Swift 中没有类型初始化器(type initializer)。
与存储的实例属性不同,您必须始终为存储的类型属性提供默认值。这是因为类型本身没有初始化器,可以在初始化时为存储的类型属性分配值。
摘自:Apple Inc. “The Swift Programming Language.” iBooks.
您可以使用默认值为闭包的类型属性(type property)。当设置该类型属性(或类变量)时,将执行闭包中的代码。
class FirstClass {
class var someProperty = {
// you can init the class member with anything you like or perform any code
return SomeType
}()
}
但是类存储属性目前还不支持
(在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
打印
开始
使用闭包设置默认属性值
因此它是延迟计算的。
static
属性来完成这个操作,就像这样:static var someProperty = { return SomeType }()
。但问题是这段代码会被惰性地运行,也就是说,只有当第一次引用该属性时才会执行。https://developer.apple.com/swift/blog/?id=7 - Aneel对于使用 @objc
的类,class func initialize()
绝对可行,因为 +initialize
是由 Objective-C 运行时实现的。但是对于“原生”的 Swift 类,你需要查看其他答案。
NSObject
的Swift类。我注意到我的类的+initialize
(实际上是override class func initialize()
)直到我调用类的方法之前都没有被调用。访问属性似乎不会触发它。也许这是因为在底层,Swift属性不像Objective-C中的方法(getter和setter)那样? - Nicolas Miari+[NSObject initialize]
的文档确实说它在类“收到第一条消息”之前被调用,所以没有理由认为类属性会触发它。 - newacctinitialize
方法。class SomeClass: {
private static let initializer: Void = {
//some initialization
}()
}
但是由于存储类型属性实际上是在第一次访问时惰性初始化的,所以您需要将它们引用到某个地方。您可以使用普通存储属性来完成此操作:
class SomeClass: {
private static let initializer: Void = {
//some initialization
}()
private let initializer: Void = SomeClass.initializer
}
@aleclarson的回答很好,但在最近的Swift 4中,您无法直接覆盖initialize
方法。但是,对于继承自NSObject
的类,您仍然可以通过Objective-C和分类实现一个带有类/静态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 上的完整文章获取详细信息!✌️
我找不到在Swift中使用+[initialize]
的任何有效用例。也许这就是它不存在的原因。
+[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类/结构体/枚举执行此操作)
CIFilter
子类的+initialize
方法中使用 +[[CIFilter registerFilterName:constructor:classAttributes:]
。 - nacho4d
+initialize
不同。在 Objective-C 中,+initialize
是在第一次向 类 发送消息时调用的。而这是在创建类的实例的第一次调用。 - newacctoverride class func initialize()
会产生警告,包括“...不能保证由Swift调用,并将在未来的版本中被禁止”。参考:https://dev59.com/r1gQ5IYBdhLWcg3wZDGd - Scott Corscadden+initialize
代码仅对类运行一次的正常和最佳方法是遵循官方文档建议(https://developer.apple.com/reference/objectivec/nsobject/1418639-initialize?language=objc) - 检查当前的self
是否为您的类,例如+ (void)initialize { if (self == [MyView self]) { /* ... do the initialization ... */ } }
。 - Slipp D. Thompsonoverride class func initialize()
是一个错误。 - ThomasW