Как узнать, кто вызвал метод?

пример: когда вызывается мой метод-fooBar, я хочу, чтобы он вошел в консоль, какой другой метод из которого вызвал его другой класс.

прямо сейчас, я знаю только, как зарегистрировать имя метода самого fooBar, и это класс, с этим:

_cmd

[self class]

можно ли это выяснить?

9 ответов


в полностью оптимизированном коде нет 100% надежного способа определить вызывающего абонента определенным методом. Компилятор может использовать оптимизацию хвостового вызова, тогда как компилятор эффективно повторно использует фрейм стека вызывающего абонента для вызываемого.

чтобы увидеть пример этого, установите точку останова для любого заданного метода с помощью gdb и посмотрите на backtrace. Обратите внимание, что перед каждым вызовом метода objc_msgSend() не отображается. Это связано с тем, что objc_msgSend() выполняет хвостовой вызов для каждого метода реализация.

хотя вы можете скомпилировать приложение без оптимизации, вам понадобятся неоптимизированные версии всех системных библиотек, чтобы избежать только этой проблемы.

и это только одна проблема; по сути, вы спрашиваете: "как мне заново изобрести CrashTracer или gdb?". Очень трудная проблема, на которой строятся карьеры. Если вы не хотите, чтобы" инструменты отладки " были вашей карьерой, я бы рекомендовал не идти по этому пути.

какой вопрос ты правда пытаешься ответить?


как о этой:

NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];

NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString  componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];

NSLog(@"Class caller = %@", [array objectAtIndex:3]);
NSLog(@"Method caller = %@", [array objectAtIndex:4]);

кредиты оригинальному автору,intropedro.


Это невозможно в общем случае, фактически не пройдя стек. Нет даже гарантии, что другой объект отправит сообщение, вызвавшее метод. Например, он может быть вызван из блока в обработчике сигналов.


посмотреть backtrace (3).


пользователь метод ниже
Передайте индекс, для которого вы хотите отобразить метод, и передайте -1, Если вы хотите отобразить полный стек метода

+(void) methodAtIndex:(int)index{
    void* callstack[128];
    int frames = backtrace(callstack, 128);
    char** strs = backtrace_symbols(callstack, frames);

    if (index == -1) {
        for (int i = 0; i < frames; ++i) {
            printf("%s\n", strs[i]);
        }
    }
    else {
        if (index < frames) {
            printf("%s\n", strs[index]);
        }
    }
    free(strs);

}

NSLog(@"Show stack trace: %@", [NSThread callStackSymbols]);

эту информацию можно получить с помощью DTrace.


создайте макрос, который добавляет __FUNCTION__ на имя функции для вызова функции. Затем этот макрос вызовет вашу функцию с дополнительным параметром char* для целевой функции.


Я пытался поймать, кто, как и когда меняет размер окна и делал какую-то ручную работу:

- (void)logWindowWidth:(NSString *)whoCalls {
   NSLog(@"%@", whoCalls);
   NSLog(@"self.window.size.width %f", self.window.size.width);
}

-(void)someMethod {
  [self logWindowWidth:@"someMethod - before"];
  ...
  [self logWindowWidth:@"someMethod - after"];
}

-(void)anotherMethod {
  [self logWindowWidth:@"anotherMethod - before"];
  ...
  [self logWindowWidth:@"anotherMethod - after"];
}