我在寻找类似于Objective-C的+(void)initialize类方法的行为,因为在初始化类时调用一次该方法,此后再也不会调用。
一个简单的class init () {}在class关闭将是非常光滑的!很明显,当我们使用"class vars"而不是"static vars in a struct closure"时,这一切都将非常匹配!
如果您有一个objective-c类,那么最简单的方法就是重写+initialize。但是,确保类的子类也覆盖+initialize,否则类的+initialize可能会被多次调用!如果您愿意,可以使用dispatch_once()(如下所述)来防止多次呼叫。
1 2 3 4 5
| class MyView : UIView {
override class func initialize () {
// Do stuff
}
} |
nbsp;
如果你有一个快速班,你能得到的最好的是dispatch_once()在init()声明内。
1 2 3 4 5 6 7 8 9
| private var once = dispatch_once_t()
class MyObject {
init () {
dispatch_once(&once) {
// Do stuff
}
}
} |
这个解决方案不同于+initialize(这是第一次给objective-c类发送消息时调用的),因此不是问题的真正答案。但我觉得它很好用。
- 你应该使用dispatch_once。
- @布莱恩陈为什么?在目标C中,保证只调用一次initialize。改变了吗?
- @sapi没有理由创建一个类并纯粹使用initialize来实现可以用dispatch_once完成的事情。
- @布莱恩-啊,明白了。我在考虑更多已经创建类的情况(我发现这个线程在搜索为什么AppDelegate.Initialize不能为我自动完成。)
- 按要求增加dispatch_once。
- 这对我有用:@objc override class func initialize()。
- 我必须将它添加到每个override init方法中吗?
- 谁说在目标C中只叫一次+initialize?它可以被多次调用:stackoverflow.com/questions/14110396/…小心!
- 这与objective-c中的+initialize不同。objective-c中的+initialize在第一次发送消息时被称为类。这是第一次创建类的实例时调用的。
- @这是真的,我应该注意到。谢谢!
- 所以对静态成员没有好处
- 您的dispatch_once方法不起作用,每次初始化类时都调用// Do stuff,这与+initialize的工作方式不同。
- 如果对象继承自NSObject,是否需要在override class func initialize()中调用super.initialize()?
- @JAL:不,在发送到子类之前,initialize会自动发送到所有超类。
- 从Swift 3.1(xcode 8.3)开始,使用override class func initialize()现在生成一个警告,包括"…不保证由SWIFT调用,在未来版本中将不允许使用。请参见:stackoverflow.com/questions/42824541/…
- 确保类只运行一次+initialize化代码的正常和最佳方法是执行官方文档建议的操作(developer.apple.com/reference/obiodic/nsobject/hellip;)-检查当前的self是否是类,例如+ (void)initialize { if (self == [MyView self]) { /* ... do the initialization ... */ } }。
- 从Swift 4开始,使用override class func initialize()是一个错误。
swift中没有类型初始值设定项。
"Unlike stored instance properties, you must always give stored type properties a default value. This is because the type itself does not have an initializer that can assign a value to a stored type property at initialization time."
摘自:苹果公司。"Swift编程语言。"iBooks。
您可以使用一个类型属性,默认值是一个闭包。因此,当设置了类型属性(或类变量)时,将执行闭包中的代码。
1 2 3 4 5 6
| 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(在xcode8中测试)。
一个答案是使用static,与class final相同。
很好的链接是
Setting a Default Property Value with a Closure or Function
摘自:苹果公司。"Swift编程语言。"iBooks。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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 |
印刷品
start
setting default property value with a closure
所以这是懒惰的评价。
- 苹果已经声明他们将在未来更新
- 你现在可以用一个static属性来实现这一点……埃多克斯1〔22〕…但问题是,代码运行缓慢,这是第一次引用属性。developer.apple.com/swift/blog/?ID=7
- @igodric"这样,当设置了类型属性(或类变量)时,将执行闭包中的代码"。你能解释一下吗?什么时候执行关闭?
- @Jarrodsmith I扩展了答案以显示一个示例。
- 为什么我们需要关闭?它不关闭就可以工作不?还是因为它是一个静态变量?
- @vandutran如果您想在创建类时使用类初始值设定项,那将只是应用程序加载方法。但是+initialize有趣的行为是,它是懒惰的(仅在首次使用类时加载值)。为了懒惰,我用了闭幕词。
对于@objc类,class func initialize()肯定有效,因为+initialize是由objective-c运行时实现的。但是对于"本地"的快速课程,你必须看到其他答案。
- 我有一个从NSObject继承的swift类。我注意到我的类的+initialize(实际上,override class func initialize()是在调用该类的方法之前不被调用的。访问属性似乎不会触发它。也许这是因为Swift属性不是像在Objective-C中那样,位于引擎盖下的方法(getter和setter)?
- @尼古拉斯米亚里:你是在说实例方法还是类方法?实例或类属性?在Objective-C中,需要调用一个类方法来创建一个实例,所以我认为在使用实例方法或实例属性之前,创建实例的行为应该触发它。如果您谈论的是类属性,那么objective-c没有类属性,因此swift的类属性可能与objc运行时不兼容,因为不需要兼容(只是猜测,我没有检查过源代码)。
- @Nicolasmiari:+[NSObject initialize]的文档确实说它是在类"发送第一条消息"之前调用的,所以没有理由认为类属性会触发它。
- 类属性,我明白了…这些方法在Objective-C中确实没有对应的方法,但是您可以通过实现两个类方法来伪造它们,这些方法的签名与实例属性的(合成的)getter和setter兼容。例如,+(void)setcolor:(uicolor*)newcolor;和+(uicolor*)color;我猜swift类属性是完全不同的beast。
@亚历克森成功了,但从最近的Swift4开始,你不能直接覆盖initialize。您仍然可以使用objective-c实现它,并且使用class/static swiftyInitialize方法来实现从MyClass.m中的objective-c调用的继承自NSObject的类的类别,这些方法包括在MyClass.swift旁边的编译源中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| # 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是一种合适的做法,你可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| # 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 |
有几个gotchas,特别是在静态库中使用这种方法时,请查看介质上的完整文章了解详细信息!???
我找不到任何有效的用例来使用类似于+[initialize]的swift。也许这就解释了它不存在的原因
为什么在objc中需要
+[initialize]?
初始化某个全局变量
1 2 3 4 5
| static NSArray *array;
+ (void)initialize {
array = @[1,2,3];
} |
哪个在雨燕
1 2 3
| struct Foo {
static let array = [1,2,3]
} |
做一些砍伐
1 2 3
| + (void)initialize {
swizzle_methodImplementation()
} |
Swift不支持(我不知道如何为纯Swift类/结构/枚举执行此操作)
- 有效的用例将用于注册nsuserdefaults
- 另一个有效的例子是曝光
- 另一个有效的用例它将类(self)注册为组的一部分。例如,《coreima编程指南》建议在CIFilter的子类+initialize中使用+[[CIFilter registerFilterName:constructor:classAttributes:]。
- 另一个有效的用例是为使用随机数的类设置一次随机函数的种子。