Je recherche un comportement similaire à la méthode de classe +(void)initialize
d'Objective-C, en ce sens que la méthode est appelée une fois lors de l'initialisation de la classe et plus jamais par la suite.
Un simple class init () {}
dans une class
fermeture serait vraiment élégant! Et évidemment, lorsque nous utiliserons "class var
s" au lieu de "static var
s dans une fermeture de structure", tout se mariera très bien!
Si vous avez une classe Objective-C, il est plus simple de remplacer +initialize
. Cependant, assurez-vous que sous-classes de votre classe annule également +initialize
sinon le +initialize
de votre classe peut être appelé plus d'une fois! Si vous le souhaitez, vous pouvez utiliser dispatch_once()
(mentionné ci-dessous) pour vous protéger contre plusieurs appels.
class MyView : UIView {
override class func initialize () {
// Do stuff
}
}
Si vous avez une classe Swift, le mieux que vous puissiez obtenir est dispatch_once()
dans la déclaration init()
.
private var once = dispatch_once_t()
class MyObject {
init () {
dispatch_once(&once) {
// Do stuff
}
}
}
Cette solution diffère de +initialize
(qui est appelée la première fois qu'une classe Objective-C est envoyée par message) et n'est donc pas une réponse vraie à la question. Mais cela fonctionne assez bien, IMO.
Il n'y a pas de type initializer dans Swift.
«Contrairement aux propriétés d'instance stockées, vous devez toujours attribuer une valeur par défaut aux propriétés de type stockées. Cela est dû au fait que le type n'a pas d'initialiseur capable d'attribuer une valeur à une propriété de type stockée au moment de l'initialisation. ”
Extrait de: Apple Inc. «Le langage de programmation Swift.» iBooks .
Vous pouvez utiliser une propriété de type} dont la valeur par défaut est une fermeture. Ainsi, le code dans la fermeture serait exécuté lorsque la propriété de type} _ (ou la variable de classe) est définie.
class FirstClass {
class var someProperty = {
// you can init the class member with anything you like or perform any code
return SomeType
}()
}
Mais class stored properties not yet supported
(testé dans Xcode 8).
Une réponse consiste à utiliser static
, c'est la même chose que class final
.
Bon lien pour cela est
Définition d'une valeur de propriété par défaut avec une fermeture ou une fonction
Extrait de: Apple Inc. «Le langage de programmation Swift.» 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
Impressions
début
définition de la valeur de propriété par défaut avec une fermeture
Donc, il est évalué paresseux.
Pour les classes @objc
, class func initialize()
fonctionne parfaitement, puisque +initialize
est implémenté par le moteur d'exécution Objective-C. Mais pour les classes Swift "natives", vous devrez voir les autres réponses.
Vous pouvez utiliser les propriétés de type stockées à la place de la méthode initialize
.
class SomeClass: {
private static let initializer: Void = {
//some initialization
}()
}
Mais comme les propriétés des types stockés sont en fait initialisées paresseusement lors de leur premier accès, vous devrez les référencer quelque part. Vous pouvez le faire avec une propriété stockée ordinaire:
class SomeClass: {
private static let initializer: Void = {
//some initialization
}()
private let initializer: Void = SomeClass.initializer
}
@aleclarson l'a cloué, mais à partir de la récente édition de Swift 4, vous ne pouvez pas remplacer directement initialize
. Vous pouvez toujours le réaliser avec Objective-C et les catégories pour les classes héritant de NSObject
avec une méthode class/static swiftyInitialize
, qui est appelée depuis Objective-C dans MyClass.m
, que vous incluez dans les sources de compilation à côté de 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
Si votre classe ne peut pas hériter de NSObject
et que l'utilisation de +load
au lieu de +initialize
convient, vous pouvez procéder comme suit:
# 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
Il y a quelques pièges, en particulier lorsque vous utilisez cette approche dans des bibliothèques statiques, consultez le média complet post sur pour plus de détails! ✌️