我正在寻找类似于Objective-C的+(void)initialize
class方法的行为,因为该方法在类初始化时被调用一次,此后不再被调用。
一个简单class init () {}
的class
闭合将非常时尚!而且很明显,当我们在结构闭包中使用“ class var
s”而不是“ static var
s”时,这一切都将非常匹配!
Answers:
如果您有一个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,但是效果很好。
initialize
保证只能被调用一次。改变了吗?
+initialize
Objective-C不同。+initialize
在Objective-C中首次调用该类的消息。这被称为第一次创建类的实例。
override class func initialize()
now会生成一条警告,包括“ ...不能保证由Swift调用,并且在以后的版本中将不允许使用...。” 请参阅:stackoverflow.com/questions/42824541/...
override class func initialize()
是一个错误。
Swift中没有类型初始值设定项。
与存储实例属性不同,您必须始终为存储类型属性赋予默认值。这是因为类型本身没有可在初始化时将值分配给存储的type属性的初始化程序。”
摘录自:苹果公司“ 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
。
好的链接是
使用闭包或函数设置默认属性值
摘录自:苹果公司“ 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 }()
...但是问题在于,该代码是在第一次引用该属性时延迟运行的。developer.apple.com/swift/blog/?id=7
对于@objc
类来说,class func initialize()
肯定是可行的,因为它+initialize
是由Objective-C运行时实现的。但是对于“本机” Swift类,您必须查看其他答案。
NSObject
。我注意到,直到我调用该类的方法时,才调用我的类+initialize
(实际上是override class func initialize()
)。访问属性似乎不会触发它。也许这是因为swift属性不是像Objective-C中那样是幕后的方法(getter和setter)?
+[NSObject initialize]
确实说在类“发送其第一条消息”之前被调用,因此没有理由认为类属性会触发它。
@aleclarson钉了它,但是从最近的Swift 4开始,您不能直接覆盖initialize
。您仍然可以使用Objective-C和NSObject
使用类/静态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
有一些陷阱,尤其是在静态库中使用此方法时,请查看Medium上的完整文章以获取详细信息!✌️
您可以使用存储的类型属性代替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
}
initializer
不是已计算的属性,因为分配的闭包实际上已执行。注意等号和结尾处的括号。如答案中所述,静态属性是延迟计算的,因此在加载类时不会立即执行闭包。而是通过在代码的其他地方引用该属性来触发它。
我找不到任何有效的用例+[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类/结构/枚举执行此操作)
+[[CIFilter registerFilterName:constructor:classAttributes:]
in+initialize
的子类CIFilter
。
dispatch_once