我正在寻找类似于Objective-C的+(void)initialize
类方法的行为,因为该方法在初始化类时被调用一次,之后再也不会被调用。
class init () {}
封闭中的简单class
非常流畅!显然,当我们在结构闭包中使用“class var
s”而不是“static var
s”时,这一切都非常匹配!
答案 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]
之类的东西。也许这解释了它不存在的方式
+[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做到这一点)