NSLog le nom de la méthode avec Objective-C dans iPhone

153

Actuellement, nous définissons nous-mêmes un mécanisme de journal étendu pour imprimer le nom de la classe et le numéro de ligne source du journal.

#define NCLog(s, ...) NSLog(@"<%@:%d> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
    __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__])

Par exemple, lorsque j'appelle NCLog (@ "Hello world"); La sortie sera:

<ApplicationDelegate:10>Hello world

Maintenant, je veux également me déconnecter du nom de la méthode comme:

<ApplicationDelegate:applicationDidFinishLaunching:10>Hello world

Ainsi, cela rendrait notre débogage plus facile lorsque nous pouvons savoir quelle méthode est appelée. Je sais que nous avons également un débogueur Xcode mais parfois, je veux aussi faire du débogage en me déconnectant.

vodkhang
la source
Dans mon dernier iPhoneprojet, je l'ai fait manuellement. J'adorerais voir la réponse à cela.
Jacob Relkin
Double

Réponses:

261
print(__FUNCTION__) // Swift
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C

Swift 3 et plus

print(#function)
dessiné
la source
120
Vous devriez vraiment utiliser NSLog(@"%@", NSStringFromSelector(_cmd)), si vous comptez utiliser _cmd, car AFAIK Apple déclare _cmdcomme type SEL, pas une chaîne C. Ce n'est pas parce qu'il se trouve qu'il est implémenté en tant que chaîne C (à partir des versions actuelles de Mac OS X et de l'iPhone OS) que vous devez l'utiliser de cette manière, car Apple pourrait le changer dans une mise à jour du système d'exploitation.
Nick Forge
5
Oui, NSStringFromSelector est la réponse la plus correcte. Je n'utilise jamais _cmd comme chaîne C pour autre chose que du code de débogage.
dessiné
Wow, le compilateur se plaint d'incompatibilité de pointeur, mais ça marche ... Donc _cmd (type: SEL) est vraiment un char *!?
Nicolas Miari
3
Méthode appelle comme [self doSomething:arg1 somethingElse:arg2]converties dans l'appel de fonction C objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);. Le deuxième paramètre de objc_msgSend()prend un char*. Rappelez-vous que parce que le runtime Objective-C est dynamique, il utilise en fait une table de recherche pour déterminer quelle méthode sur quelle classe appeler, donc un char * est pratique car les méthodes sont représentées sous forme de chaînes dans la table de recherche.
Jack Lawrence
1
Pour Swift 2.2 devrait utiliserprint("\(#function)")
Jake Lin
161

Pour répondre techniquement à votre question, vous souhaitez:

NSLog(@"<%@:%@:%d>", NSStringFromClass([self class]), NSStringFromSelector(_cmd), __LINE__);

Ou vous pouvez également faire:

NSLog(@"%s", __PRETTY_FUNCTION__);
Dave DeLong
la source
2
Avec __FUNCTION__et son assez équivalent étant également disponible dans les fonctions C.
Georg Fritzsche
NB __FUNCTION__inclut également le nom de la classe
OrangeDog
1
y a-t-il une différence en utilisant NSLog (@ "% s", _func_ ); OU NSLog (@ "% s", _PRETTY_FUNCTION_ ) ???
Ravi
83

tl; dr

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

Détails

Apple a une page de questions / réponses techniques: QA1669 - Comment puis-je ajouter des informations de contexte - telles que la méthode actuelle ou le numéro de ligne - à mes instructions de journalisation?

Pour aider à la journalisation:

  • Le préprocesseur C fournit quelques macros .
  • Objective-C fournit des expressions (méthodes).
    • Passez l' argument implicite pour le sélecteur de la méthode actuelle:_cmd

Comme d'autres réponses l'indiquent, pour obtenir simplement le nom de la méthode actuelle, appelez:

NSStringFromSelector(_cmd)

Pour obtenir le nom de la méthode actuelle et le numéro de ligne actuel, utilisez ces deux macros __func__et __LINE__comme indiqué ici:

NSLog(@"%s:%d someObject=%@", __func__, __LINE__, someObject);

Un autre exemple… Des extraits de code que je garde dans la bibliothèque d'extraits de code de Xcode:

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

… Et TRACE au lieu de ERROR…

NSLog( @"TRACE %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

… Et une plus longue utilisant une description codée en logiciel passant une valeur ( [rows count])…

NSLog( @"TRACE %@ METHOD %s:%d.", [NSString stringWithFormat:@"'Table of Contents.txt' file's count of Linefeed-delimited rows: %u.", [rows count]] , __func__, __LINE__ );

Macros de préprocesseur pour la journalisation

Notez l'utilisation d'une paire de caractères de soulignement autour des deux côtés de la macro.

| Macro | Format | La description
  __func__% s Signature de la fonction actuelle
  __LINE__% d Numéro de ligne actuel
  __FILE__% s Chemin complet du fichier source
  __PRETTY_FUNCTION__% s Comme __func__, mais inclut des informations détaillées
                                    tapez les informations dans le code C ++. 

Expressions pour la journalisation

| Expression | Format | La description
  NSStringFromSelector (_cmd)% @ Nom du sélecteur actuel
  NSStringFromClass ([self class])% @ Nom de classe de l'objet actuel
  [[NSString% @ Nom du fichier de code source
    stringWithUTF8String: __ FILE__]   
    lastPathComponent] 
  [NSThread callStackSymbols]% @ NSArray de trace de pile

Cadres de journalisation

Certains cadres de journalisation peuvent également aider à obtenir la méthode actuelle ou le numéro de ligne. Je ne suis pas sûr, car j'ai utilisé un excellent cadre de journalisation en Java ( SLF4J + LogBack ) mais pas Cocoa.

Consultez cette question pour obtenir des liens vers divers cadres de journalisation Cocoa.

Nom du sélecteur

Si vous avez une variable Selector (un SEL ), vous pouvez imprimer son nom de méthode ("message") de l'une des deux manières décrites dans ce billet de blog Codec :

  • Utilisation de l'appel Objective-C à NSStringFromSelector :
    NSLog(@"%@", NSStringFromSelector(selector) );
  • En utilisant directement C:
    NSLog(@"%s", selector );

Ces informations sont tirées de la page de documentation Apple liée au 19/07/2013. Cette page a été mise à jour le 2011-10-04.

Basil Bourque
la source
1
Pour C, utilisez sel_getName(SEL)puisque SEL est un type opaque et peut ne pas toujours être unchar *
Ethan Reesor
8
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C
print(__FUNCTION__) // Swift
Huynh Inc
la source
4
Pour tous ceux qui rencontrent cette réponse à l'avenir: elle équivaut à la réponse acceptée, mais la réponse acceptée était différente, lorsque celle-ci a été publiée (la réponse acceptée a été modifiée en 2014). J'étais sur le point de voter, mais après une petite enquête
j'ai
0

C'est en fait aussi simple que:

printf(_cmd);

Pour une raison quelconque, iOS permet à _cmd d'être passé en tant que caractère littéral sans même d'avertissement de compilation. Qui sait

Albert Renshaw
la source
0

Dans Swift 4:

test func () {

print(#function)

}

test () // affiche la valeur "test ()"

Garg Ankit
la source