Wenn Sie eine Objective-C-Klasse haben, ist es am einfachsten, diese einfach zu überschreiben +initialize
. Stellen Sie jedoch sicher, dass Unterklassen Ihrer Klasse ebenfalls überschrieben werden, da +initialize
sonst die Klassen Ihrer Klasse +initialize
möglicherweise mehrmals aufgerufen werden! Wenn Sie möchten, können Sie dispatch_once()
(siehe unten) zum Schutz vor mehreren Anrufen verwenden.
class MyView : UIView {
override class func initialize () {
}
}
Wenn Sie eine Swift-Klasse haben, ist das Beste, was Sie bekommen können, dispatch_once()
in der init()
Anweisung.
private var once = dispatch_once_t()
class MyObject {
init () {
dispatch_once(&once) {
}
}
}
Diese Lösung unterscheidet sich von +initialize
(die beim ersten Messaging einer Objective-C-Klasse aufgerufen wird) und ist daher keine echte Antwort auf die Frage. Aber es funktioniert gut genug, IMO.
dispatch_once
initialize
wurde garantiert, dass es nur einmal aufgerufen wird. Hat sich das geändert?+initialize
Objective-C.+initialize
In Objective-C wird das erste Mal aufgerufen, wenn die Klasse eine Nachricht erhält . Dies wird beim ersten Erstellen einer Instanz der Klasse aufgerufen.override class func initialize()
now eine Warnung generiert, die "... nicht garantiert von Swift aufgerufen wird und in zukünftigen Versionen nicht mehr zulässig ist". Siehe: stackoverflow.com/questions/42824541/…override class func initialize()
ein Fehler.In Swift gibt es keinen Typinitialisierer .
Auszug aus: Apple Inc. "Die schnelle Programmiersprache". iBooks .
Sie können eine type-Eigenschaft verwenden, deren Standardwert ein Abschluss ist. Der Code im Abschluss würde also ausgeführt, wenn die Eigenschaft type (oder die Klassenvariable) festgelegt wird.
class FirstClass { class var someProperty = { // you can init the class member with anything you like or perform any code return SomeType }() }
Aber
class stored properties not yet supported
(getestet in Xcode 8).Eine Antwort ist zu verwenden
static
, es ist die gleiche wieclass final
.Guter Link dafür ist
Auszug aus: Apple Inc. "Die schnelle Programmiersprache". iBooks .
Codebeispiel:
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
Druckt
Also ist es faul ausgewertet.
quelle
static
jetzt mit einer Eigenschaft tun,static var someProperty = { return SomeType }()
aber das Problem ist, dass dieser Code beim ersten Verweisen auf die Eigenschaft träge ausgeführt wird. developer.apple.com/swift/blog/?id=7Für
@objc
Klassenclass func initialize()
funktioniert das definitiv, da+initialize
es von der Objective-C-Laufzeit implementiert wird. Aber für "native" Swift-Klassen müssen Sie die anderen Antworten sehen.quelle
NSObject
. Ich habe Hinweise, dass meine Klasse+initialize
(eigentlichoverride class func initialize()
) erst aufgerufen wird, wenn ich eine Methode der Klasse aufrufe. Der Zugriff auf Eigenschaften scheint dies nicht auszulösen. Vielleicht liegt das daran, dass schnelle Eigenschaften keine Methoden (Getter und Setter) unter der Haube sind, wie in Objective-C?+[NSObject initialize]
besagt, dass es aufgerufen wird, bevor der Klasse "ihre erste Nachricht gesendet wird". Es gibt also keinen Grund zu der Annahme, dass Klasseneigenschaften es trotzdem auslösen würden.@aleclarson hat es geschafft, aber ab dem letzten Swift 4 können Sie nicht direkt überschreiben
initialize
. Sie können dies weiterhin mit Objective-C und Kategorien für Klassen erreichen, von denenNSObject
mit einer class / static-swiftyInitialize
Methode geerbt wird, die von Objective-C in aufgerufen wirdMyClass.m
und die Sie nebenMyClass.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
Wenn Ihre Klasse nicht von erben erben kann
NSObject
und+load
stattdessen+initialize
eine geeignete Anpassung verwendet, können Sie Folgendes tun:# 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
Es gibt einige Fallstricke, insbesondere wenn Sie diesen Ansatz in statischen Bibliotheken verwenden. Weitere Informationen finden Sie im vollständigen Beitrag auf Medium! ✌️
quelle
Sie können gespeicherte Typeneigenschaften anstelle der
initialize
Methode verwenden.class SomeClass: { private static let initializer: Void = { //some initialization }() }
Da die Eigenschaften gespeicherter Typen beim ersten Zugriff tatsächlich träge initialisiert werden, müssen Sie sie irgendwo weiterleiten. Sie können dies mit gewöhnlichen gespeicherten Objekten tun:
class SomeClass: { private static let initializer: Void = { //some initialization }() private let initializer: Void = SomeClass.initializer }
quelle
initializer
ist keine berechnete Eigenschaft, da der zugewiesene Abschluss tatsächlich ausgeführt wird. Beachten Sie das Gleichheitszeichen und die Klammern am Ende. Wie in der Antwort erwähnt, werden statische Eigenschaften träge ausgewertet, sodass der Abschluss beim Laden der Klasse nicht sofort ausgeführt wird. Stattdessen wird es ausgelöst, indem auf die Eigenschaft an einer anderen Stelle im Code verwiesen wird.Ich kann keinen gültigen Anwendungsfall finden, um so etwas wie
+[initialize]
in Swift zu haben. Vielleicht erklärt dies, wie es nicht existiertWarum brauchen wir
+[initialize]
in ObjC?Initialisieren einer globalen Variablen
static NSArray *array; + (void)initialize { array = @[1,2,3]; }
was in Swift
struct Foo { static let array = [1,2,3] }
Um etwas zu hacken
was von Swift nicht unterstützt wird (ich kann nicht herausfinden, wie es für die reine Swift-Klasse / struct / enum geht)
quelle
+[[CIFilter registerFilterName:constructor:classAttributes:]
in+initialize
den Subklassen vonCIFilter
.