NSLog назва методу за допомогою Objective-C в iPhone


153

В даний час ми визначаємо розширений механізм журналу для друку назви класу та номера рядка джерела журналу.

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

Наприклад, коли я дзвоню NCLog (@ "Hello world"); Вихід буде:

<ApplicationDelegate:10>Hello world

Тепер я також хочу вийти з назви методу, наприклад:

<ApplicationDelegate:applicationDidFinishLaunching:10>Hello world

Отже, це зробить нашу налагодження простішим, коли ми можемо знати, який метод викликається. Я знаю, що у нас також є налагоджувач Xcode, але іноді я також хочу робити налагодження, виходячи з системи.


У своєму останньому iPhoneпроекті я насправді робив це вручну. Я хотів би побачити відповідь на це.
Яків Релькін

Можливий дублікат: stackoverflow.com/questions/969130 / ...
erkanyildiz

Відповіді:


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

Швидкість 3 і вище

print(#function)

120
Ви дійсно повинні використовувати NSLog(@"%@", NSStringFromSelector(_cmd)), якщо ви збираєтесь використовувати _cmd, оскільки AFAIK Apple оголошує _cmdяк тип SEL, а не C-рядок. Тільки тому, що він може бути реалізований як C-рядок (як і в сучасних версіях Mac OS X та iPhone OS), не означає, що ви повинні використовувати його таким чином, оскільки Apple може змінити його в оновленнях ОС.
Нік Форж

5
Так, правильніша відповідь - NSStringFromSelector. Я ніколи не використовую _cmd як рядок c ні для чого, крім коду налагодження.
розіграш

Нічого собі, компілятор скаржиться на несумісність указівника, але він працює ... Тож _cmd (type: SEL) справді є char * !?
Nicolas Miari

3
Метод вимагає , як [self doSomething:arg1 somethingElse:arg2]перетворюється в виклик функції C objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);. Другий параметр objc_msgSend()take a char*. Пам’ятайте, що оскільки час виконання Objective-C є динамічним, він фактично використовує таблицю пошуку, щоб визначити, яким методом, для якого класу викликати так char *, зручно, оскільки методи представлені у вигляді рядків у таблиці пошуку.
Джек Лоуренс

1
Для Swift 2.2 слід використовуватиprint("\(#function)")
Джейк Лін

161

Щоб технічно відповісти на ваше запитання, потрібно:

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

Або ви також можете зробити:

NSLog(@"%s", __PRETTY_FUNCTION__);

2
З, __FUNCTION__а також його еквівалент також доступний у C-функціях.
Георг Фріцше

NB __FUNCTION__також включає назву класу
OrangeDog

1
чи є різниця за допомогою NSLog (@ "% s", _func_ ); АБО NSLog (@ "% s", _PRETTY_FUNCTION_ ) ???
Раві

83

тл; д-р

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

Деталі

Apple має сторінку технічних запитань та запитів : QA1669 - Як я можу додати інформацію про контекст - наприклад, поточний метод чи номер рядка - до моїх заяв про реєстрацію?

Щоб допомогти в реєстрації:

  • Препроцесор C забезпечує кілька макросів .
  • Objective-C забезпечує вирази (методи).
    • Передайте неявний аргумент для селектора поточного методу:_cmd

Як зазначено в інших відповідях, щоб просто отримати назву поточного методу, зателефонуйте:

NSStringFromSelector(_cmd)

Щоб отримати поточне ім'я методи і номер поточного рядка, використовуйте ці два макрос __func__і , __LINE__як показано тут:

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

Інший приклад… Фрагменти коду, який я зберігаю в бібліотеці фрагментів коду Xcode:

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

… І TRACE замість помилки…

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

… І довший, використовуючи опис з м'яким кодом, передаючи значення ( [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__ );

Препроцесорні макроси для ведення журналу

Зверніть увагу на використання пари символів підкреслення навколо обох сторін макросу.

| Макрос | Формат | Опис
  __func__% s Підпис поточної функції
  __LINE__% d Поточний номер рядка
  __FILE__% s Повний шлях до вихідного файлу
  __PRETTY_FUNCTION__% s Як і __func__, але включає багатослівне
                                    введіть інформацію в код C ++. 

Вирази для ведення журналів

| Вираз | Формат | Опис
  NSStringFromSelector (_cmd)% @ Ім'я поточного селектора
  NSStringFromClass ([самоклас])% @ Ім'я класу поточного об'єкта
  [[NSString% @ ім'я файлу вихідного коду
    stringWithUTF8String: __ FILE__]   
    lastPathComponent] 
  [NSThread callStackSymbols]% @ NSArray сліду стека

Рамки ведення журналів

Деякі рамки реєстрації можуть також допомогти отримати поточний метод або номер рядка. Я не впевнений, оскільки я використовував чудовий фреймворк журналу в Java ( SLF4J + LogBack ), але не какао.

Дивіться це запитання для посилань на різні рамки реєстрації какао.

Ім'я селектора

Якщо у вас є змінна Selector ( SEL ), ви можете роздрукувати її ім'я методу ("message") будь-яким із двох способів, як описано у цій публікації блогу Codec :

  • Використання виклику Objective-C на NSStringFromSelector :
    NSLog(@"%@", NSStringFromSelector(selector) );
  • Використання прямої C:
    NSLog(@"%s", selector );

Ця інформація, отримана із пов’язаної сторінки документа Apple, станом на 19.07.2013. Ця сторінка востаннє оновлена ​​2011-10-04.


1
Для C використовуйте, sel_getName(SEL)оскільки SEL є непрозорим типом і не завжди може бутиchar *
Етан Резор

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

4
Для всіх, хто в майбутньому стикається з цією відповіддю: вона рівнозначна прийнятій відповіді, але прийнята відповідь була іншою, коли вона була розміщена (прийнята відповідь була відредагована у 2014 році). Я збирався проголосувати, але замість невеликого розслідування проголосував натомість :)
FreeNickname

0

Це насправді так само просто, як:

printf(_cmd);

Чомусь iOS дозволяє передавати _cmd як буквальну таблицю з навіть не попередженням про компіляцію. Хто знає


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.