ios Swift 中类的“初始化”类方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24137212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:45:55  来源:igfitidea点击:

"initialize" class method for classes in Swift?

iosswift

提问by aleclarson

I'm looking for behavior similar to Objective-C's +(void)initializeclass method, in that the method is called once when the class is initialized, and never again thereafter.

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

A simple class init () {}in a classclosure would be really sleek! And obviously when we get to use "class vars" instead of "static vars in a struct closure", this will all match really well!

一个简单class init () {}class闭合将非常时尚!很明显,当我们在结构闭包中使用“ class vars”而不是“ static vars”时,这一切都会非常匹配!

采纳答案by aleclarson

If you have an Objective-C class, it's easiest to just override +initialize. However, make sure subclassesof your class also override +initializeor else your class's +initializemay get called more than once! If you want, you can use dispatch_once()(mentioned below) to safeguard against multiple calls.

如果您有一个 Objective-C 类,最简单的方法是覆盖+initialize. 但是,请确保您的类的类也被覆盖+initialize,否则您的类+initialize可能会被多次调用!如果需要,您可以使用dispatch_once()(如下所述)来防止多次调用。

class MyView : UIView {
  override class func initialize () {
    // Do stuff
  }
}

 

 

If you have a Swift class, the best you can get is dispatch_once()inside the init()statement.

如果你有一个 Swift 类,你能得到的最好的就是dispatch_once()init()语句中。

private var once = dispatch_once_t()

class MyObject {
  init () {
    dispatch_once(&once) {
      // Do stuff
    }
  }
}

This solution differs from +initialize(which is called the first time an Objective-C class is messaged) and thus isn't a true answer to the question. But it works good enough, IMO.

此解决方案不同于+initialize(第一次向 Objective-C 类发送消息时称为),因此不是问题的真正答案。但它工作得很好,IMO。

回答by Binarian

There is no type initializerin Swift.

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 initializerthat can assign a value to a stored type property at initialization time.”

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

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.

摘自:Apple Inc. “The Swift Programming Language”。电子书



You could use a type propertywhich default value is a closure. So the code in the closure would be executed when the type property(or class variable) is set.

您可以使用默认值为闭包的类型属性。因此,当设置类型属性(或类变量)时,将执行闭包中的代码。

class FirstClass {
    class var someProperty = {
     // you can init the class member with anything you like or perform any code
        return SomeType
    }()
}

But class stored properties not yet supported(tested in Xcode 8).

但是class stored properties not yet supported(在 Xcode 8 中测试)。

One answer is to use static, it is the same as class final.

一个答案是使用static,它与class final.

Good link for that is

好的链接是

Setting a Default Property Value with a Closure or Function

使用闭包或函数设置默认属性值

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.

摘自:Apple Inc. “The Swift Programming Language”。电子书



Code example:

代码示例:

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

Prints

印刷

start

setting default property value with a closure

开始

使用闭包设置默认属性值

So it is lazy evaluated.

所以它是懒惰的评估。

回答by newacct

For @objcclasses, class func initialize()definitely works, since +initializeis implemented by the Objective-C runtime. But for "native" Swift classes, you'll have to see the other answers.

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

回答by Ian Bytchek

@aleclarson nailed it, but as of recent Swift 4 you cannot directly override initialize. You still can achieve it with Objective-C and categories for classes inheriting from NSObjectwith a class / static swiftyInitializemethod, which gets invoked from Objective-C in MyClass.m, which you include in compile sources alongside MyClass.swift:

@aleclarson 搞定了,但从最近的 Swift 4 开始,你不能直接覆盖initialize. 您仍然可以使用 Objective-C 实现它,并NSObject使用类/静态swiftyInitialize方法继承类的类别,该方法从 Objective-C in 中调用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

If your class cannot inherit from NSObjectand using +loadinstead of +initializeis a suitable fit, you can do something like this:

如果你的类不能继承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

There are couple of gotchas, especially when using this approach in static libraries, check out the complete poston Medium for details! ??

有几个问题,尤其是在静态库中使用这种方法时,请查看Medium 上的完整帖子了解详细信息!??

回答by Cy-4AH

You can use stored type properties instead of initializemethod.

您可以使用存储类型属性而不是initialize方法。

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

But since stored types properties are actually lazily initialized on their first access, you will need refer them somewhere. You can do this with ordinary stored property:

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

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

回答by Bryan Chen

I can't find any valid use case to have something like +[initialize]in Swift. Maybe this explains way it does not exist

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

Why do we need +[initialize]in ObjC?

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

To initialize some global variable

初始化一些全局变量

static NSArray *array;

+ (void)initialize {
    array = @[1,2,3];
}

which in Swift

在 Swift 中

struct Foo {
    static let array = [1,2,3]
}


To do some hack

做一些黑客

+ (void)initialize {
    swizzle_methodImplementation()
}

which is not supported by Swift (I can't figure out how to do it for pure Swift class/struct/enum)

Swift 不支持它(我不知道如何为纯 Swift 类/结构/枚举做到这一点)