Je suis très nouveau dans la langue Swift
Je voulais déclarer une fonction en ligne comme en c ++ donc ma déclaration amusante est comme
func MyFunction(param: Int) -> Int {
...
...
...
}
et je veux faire quelque chose comme
inline func MyFunction(param: Int) -> Int {
...
...
...
}
J'ai essayé de rechercher sur le Web mais je n'ai rien trouvé de pertinent peut-être qu'il n'y a pas de mot-clé en ligne mais peut-être qu'il y a une autre façon d'inclure la fonction
Merci beaucoup :)
Swift 1.2 inclura l'attribut @inline
, Avec never
et __always
Comme paramètres. Pour plus d'informations, voir ici .
Comme indiqué précédemment, vous devez rarement déclarer une fonction explicitement en tant que @inline(__always)
car Swift est assez intelligent pour savoir quand incorporer une fonction. Cependant, ne pas avoir de fonction en ligne, peut être nécessaire dans certains codes.
Tout crédit à la réponse , résumant simplement les informations de la lien .
Pour rendre une fonction en ligne, ajoutez simplement @inline(__always)
avant la fonction:
@inline(__always) func myFunction() {
}
Cependant, cela vaut la peine d'envisager et d'en apprendre davantage sur les différentes possibilités. Il existe trois façons possibles de s'aligner:
@inline(__always)
avant la fonction. Utilisez "si votre fonction est plutôt petite et que vous préférez que votre application s'exécute plus rapidement".@inline(never)
avant la fonction. Utilisez "si votre fonction est assez longue et que vous souhaitez éviter d'augmenter la taille de votre segment de code".Je suis tombé sur un problème que j'avais besoin d'utiliser les attributs @inlinable
Et @usableFromInline
Qui ont été introduits dans Swift 4.2, donc je voudrais partager mon expérience avec vous.
Permettez-moi de passer directement au problème, notre base de code a un module Analytics Facade qui relie d'autres modules.
Cible d'application -> module Analytics Facade -> module de création de rapports X.
Le module Analytics Facade possède une fonction appelée report(_ rawReport: EventSerializable)
qui déclenche les appels de rapport. Cette fonction utilise une instance du module de rapport X pour envoyer les appels de rapport pour ce module de rapport spécifique X.
Le fait est que le fait d'appeler cette fonction report(_ rawReport: EventSerializable)
plusieurs fois pour envoyer les appels de rapport une fois que les utilisateurs lancent l'application crée des frais généraux inévitables qui nous ont causé beaucoup de plantages.
De plus, il n'est pas facile de reproduire ces plantages si vous définissez Optimisation level
Sur None
en mode débogage. Dans mon cas, je n'ai pu le reproduire que lorsque j'ai défini le Optimisation level
Sur Fastest, Smalles
T ou même plus.
La solution consistait à utiliser @inlinable
Et @usableFromInline
.
L'utilisation de @inlinable
Et @usableFromInline
Exporte le corps d'une fonction dans le cadre de l'interface d'un module, le rendant disponible pour l'optimiseur lorsqu'il est référencé à partir d'autres modules.
L'attribut @usableFromInline
Marque une déclaration interne comme faisant partie de l'interface binaire d'un module, lui permettant d'être utilisée à partir du code @inlinable
Sans l'exposer comme faisant partie de l'interface source du module.
À travers les limites des modules, les génériques d'exécution introduisent une surcharge inévitable, car les métadonnées de type réifié doivent être transmises entre les fonctions, et divers modèles d'accès indirect doivent être utilisés pour manipuler les valeurs de type générique. Pour la plupart des applications, cette surcharge est négligeable par rapport au travail réel effectué par le code lui-même.
Un binaire client construit par rapport à ce cadre peut appeler ces fonctions génériques et bénéficier d'une amélioration possible des performances lorsqu'il est construit avec des optimisations activées, en raison de l'élimination de la surcharge d'abstraction.
Exemple de code:
@inlinable public func allEqual<T>(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
var iter = seq.makeIterator()
guard let first = iter.next() else { return true }
func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec(&iter)
}
return rec(&iter)
}
Plus d'informations - Inline et spécialisation inter-modules