Est-ce que Swift prend actuellement en charge les macros, ou est-il prévu d’ajouter la prise en charge actuellement? Je diffuse actuellement:
Log.trace(nil, function: __FUNCTION__, file: __FILE__, line: __LINE__)
Dans divers endroits de mon code.
Dans ce cas, vous devez ajouter une valeur par défaut pour les paramètres "macro".
Swift 2.2 et supérieur
func log(message: String,
function: String = #function,
file: String = #file,
line: Int = #line) {
print("Message \"\(message)\" (File: \(file), Function: \(function), Line: \(line))")
}
log("Some message")
Swift 2.1 et inférieur
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
print("Message \"\(message)\" (File: \(file.lastPathComponent), Function: \(function), Line: \(line))")
}
log("Some message")
C'est ce que font les fonctions fatalError
et assert
.
Il n'y a pas d'autres macros à l'exception de la compilation conditionnelle déjà mentionnée dans une autre réponse.
Les Apple docs indiquent que:
Déclarez des macros simples en tant que constantes globales et traduisez des macros complexes en fonctions.
Vous pouvez toujours utiliser # if/# else/# endif - mais mon sentiment est qu'ils n'introduiront pas de fonctions macro, le langage n'en a tout simplement pas besoin.
Depuis XCode 7.3, le __FILE__
__FUNCTION__
et __LINE__
les constantes de compilation sont devenues les plus belles #file
#function
et #line
respectivement.
lastPathComponent
a besoin d'un NSURL
, j'ai donc changé le code ci-dessus en ceci:
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
let url = NSURL(fileURLWithPath: file)
print("Message \"\(message)\" (File: \(url.lastPathComponent ?? "?"), Function: \(function), Line: \(line))")
}
log("some message")
Voici une mise à jour Swift 2 réponse.
func LogW(msg:String, function: String = #function, file: String = #file, line: Int = #line){
print("[WARNING]\(makeTag(function, file: file, line: line)) : \(msg)")
}
private func makeTag(function: String, file: String, line: Int) -> String{
let url = NSURL(fileURLWithPath: file)
let className = url.lastPathComponent ?? file
return "\(className) \(function)[\(line)]"
}
Exemple d'utilisation:
LogW("Socket connection error: \(error)")
Les macros sont mauvaises, mais parfois vous en avez juste besoin. Par exemple, j'ai
struct RegionEntity {
var id: Int!
}
Et je veux placer des instances de cette structure sur Set. Je dois donc le conformer au protocole Hashable.
extension RegionEntity: Hashable {
public var hashValue: Int {
return id
}
}
public func ==(first: RegionEntity, second: RegionEntity) -> Bool {
return first.id == second.id
}
Génial. Mais que se passe-t-il si j'ai des dizaines de telles structures et que la logique est la même? Je peux peut-être déclarer un protocole et le conformer implicitement à Hashable. Allons vérifier:
protocol Indexable {
var id: Int! { get }
}
extension Indexable {
var hashValue: Int {
return id
}
}
func ==(first: Indexable, second: Indexable) -> Bool {
return first.id == second.id
}
Et bien ça marche. Et maintenant, je vais conformer ma structure aux deux protocoles:
struct RegionEntity: Indexable, Hashable {
var id: Int!
}
Nan. Je ne peux pas faire cela, car Equatable requiert l'opérateur == avec Self et il n'y a pas d'opérateur == pour RegionEntity. Swift m'oblige à copier-coller le code de confirmation pour chaque structure et juste changer le nom. Avec la macro, je pouvais le faire avec une seule ligne.