Il est possible d'ajouter des extensions aux types d'objet Swift existants à l'aide d'extensions, comme décrit dans la spécification de langage .
En conséquence, il est possible de créer des extensions telles que:
extension String {
var utf8data:NSData {
return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
}
}
Cependant, quelle est la meilleure pratique de dénomination pour les fichiers source Swift contenant de telles extensions?
Auparavant, la convention consistait à utiliser extendedtype+categoryname.m
pour le type Objective-C Comme indiqué dans le guide Objective-C . Mais l'exemple de Swift n'a pas de nom de catégorie et l'appel de String.Swift
ne semble pas approprié.
La question est donc: étant donné l'extension String
ci-dessus, comment le fichier source Swift doit-il être appelé?
La plupart des exemples que j'ai vus imitent l'approche Objective-C. L'extension d'exemple ci-dessus serait:
String+UTF8Data.Swift
L'avantage est que la convention de dénomination permet de comprendre facilement qu'il s'agit d'une extension et de la classe en cours d'extension.
Le problème avec Extensions.Swift
ou même StringExtensions.Swift
est qu’il n’est pas possible de déduire l’objet du fichier par son nom sans regarder son contenu.
Utiliser l'approche xxxable.Swift
utilisée par Java fonctionne bien pour les protocoles ou les extensions qui ne définissent que des méthodes. Mais encore une fois, l’exemple ci-dessus définit un attribut de sorte que UTF8Dataable.Swift
n’a pas beaucoup de sens grammatical.
Il n'y a pas de convention Swift. Rester simple:
StringExtensions.Swift
Je crée un fichier pour chaque classe que je développe. Si vous utilisez un seul fichier pour toutes les extensions, il deviendra rapidement une jungle.
Ma préférence est de mettre "Extension_" au début du fichier. (Je mets toutes les extensions associées dans le même fichier.)
Ainsi, tous les fichiers d’extension sont regroupés, par ordre alphabétique, dans le répertoire de mon application et dans le navigateur de Xcode. Bien sûr, dans le navigateur, je peux aussi les regrouper.
Ainsi, une extension liée à la chaîne irait dans Extension_String.Swift
Je préfère StringExtensions.Swift
jusqu'à ce que j'ajoute trop d'éléments pour diviser le fichier en quelque chose comme String+utf8Data.Swift
et String+Encrypt.Swift
.
Une dernière chose, combiner des fichiers similaires en un seul rendra votre bâtiment plus rapide. Reportez-vous à Optimizing-Swift-Build-Times
Si vous disposez d'un ensemble d'améliorations communes et diverses convenues par l'équipe, regroupez-les en tant qu'extensions. Swift fonctionne en tant que solution Keep-It-Simple de premier niveau. Cependant, au fur et à mesure que votre complexité augmente ou que les extensions deviennent plus complexes, une hiérarchie est nécessaire pour encapsuler la complexité. Dans de telles circonstances, je recommande la pratique suivante avec un exemple.
J'ai eu un cours qui s'adresse à mon serveur, appelé Server
. Il a commencé à grossir pour couvrir deux applications cibles différentes. Certaines personnes aiment les gros fichiers mais se séparent logiquement avec des extensions. Ma préférence est de garder chaque fichier relativement court, j'ai donc choisi la solution suivante. Server
était à l'origine conforme à CloudAdapterProtocol
et implémentait toutes ses méthodes. Ce que j'ai fait était de transformer le protocole en une hiérarchie, en le faisant référence à des protocoles subordonnés:
protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
var server: CloudServer {
get set
}
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void)
}
Dans Server.Swift
j'ai
import Foundation
import UIKit
import Alamofire
import AlamofireImage
class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) {
.
.
}
Server.Swift
implémente alors simplement l'API du serveur principal pour configurer le serveur et obtenir la version de l'API. Le vrai travail est divisé en deux fichiers:
Server_ReggyCloudProtocol.Swift
Server_ProReggyCloudProtocol.Swift
Ceux-ci implémentent les protocoles respectifs.
Cela signifie que vous devez avoir des déclarations d'importation dans les autres fichiers (pour Alamofire dans cet exemple), mais c'est une solution propre en termes de séparation des interfaces à mon avis.
Je pense que cette approche fonctionne aussi bien avec les classes spécifiées de l'extérieur que les vôtres.