Jak zarejestrować wszystkie metody używane w aplikacji iOS

Przejmuję prace nad aplikacją na iPada dla klienta. Jest sporo pracy, która została już wykonana i staram się poskładać w całość, jak to wszystko jest zaprojektowane, aby działać.

Jedną z rzeczy, które chciałbym zrobić, to dziennik, które metody są wywoływane, gdy aplikacja działa. Widziałem Niestandardowy skrypt DTrace, który ma zapisywać wszystkie metody od startu, ale kiedy uruchamiam go w instrumentach, nie mam żadnych wyników.

Jaki jest najlepszy sposób logowania metody?

Author: Adam Wright, 2011-09-01

8 answers

Zainspirowany odpowiedzią tc na podobne pytanie tutaj, stworzyłem akcję debug breakpoint, która wyloguje nazwę klasy i metody za każdym razem, gdy objc_msgSend() zostanie uruchomiona w Twojej aplikacji. Działa to podobnie do skryptu DTrace, który opisałem w tej odpowiedzi .

Aby włączyć tę akcję punktu przerwania, utwórz nowy symboliczny punkt przerwania( w Xcode 4 przejdź do nawigatora punktów przerwania i utwórz nowy symboliczny punkt przerwania za pomocą plusa w lewym dolnym rogu okno). Niech symbol będzie objc_msgSend, ustaw go na automatycznie Kontynuuj po wykonaniu czynności i ustaw akcję jako polecenie debuggera, używając następującego polecenia:

printf "[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)),*(long *)($esp+8)

Twój punkt przerwania powinien wyglądać mniej więcej tak:

Akcja punktu przerwania

To powinno wylogowywać się z takich wiadomości, gdy są uruchamiane na Twojej aplikacji:

[UIApplication sharedApplication]
[UIApplication _isClassic]
[NSCFString getCString:maxLength:encoding:]
[UIApplication class]
[SLSMoleculeAppDelegate isSubclassOfClass:]
[SLSMoleculeAppDelegate initialize]

Jeśli zastanawiasz się, gdzie wyciągnąłem adresy pamięci, przeczytaj Ten artykuł Phrack na temat wewnętrznych runtime Objective-C. Na powyższe adresy pamięci będą działać tylko na symulatorze, więc może być konieczne dostosowanie tego, aby działać na aplikacjach na urządzeniach z systemem iOS. Collin sugeruje następującą modyfikację w swojej odpowiedzi , aby uruchomić to na urządzeniu:

printf "[%s %s]\n", (char *)object_getClassName($r0),$r1

Myślę również, że zobaczysz, że wylogowanie każdej metody wywołanej w Twojej aplikacji przytłoczy Cię informacjami. Możesz być w stanie użyć pewnych warunków, aby to filtrować, ale nie wiem, czy to pomoże Ci dowiedzieć się, jak Twój kod wykonuje.

 56
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:15

Jeśli używasz LLDB, musisz użyć następujących poleceń debuggera. Zostały one Przetestowane w Xcode 4.6.

Urządzenie:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($r0),$r1)

Symulator:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName(*(long*)($esp+4)), *(long *)($esp+8))
 19
Author: warhammerkid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-09 22:54:08

Aby prześledzić kod aplikacji pod Xcode 6 na urządzeniu, musiałem użyć następującego wyrażenia debuggera.

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($arg1),$arg2)
 7
Author: Zmicier Zaleznicenka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-19 07:45:21

Podejście Brada Larsona można dostosować do pracy na urządzeniu za pomocą polecenia debugger:

printf "[%s %s]\n", (char *)object_getClassName($r0),$r1

Więcej informacji można znaleźć w notce technicznej tutaj: technotes

 5
Author: Collin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-15 05:10:47

Późniejsze wersje xcode trzeba tak wołać

expr -- (void)printf("[%s, %s]\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8) )
 4
Author: Ali Kıran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-01 21:38:56

Jeśli chcesz ograniczyć wyjście tylko do wiadomości wysyłanych do jednej klasy, możesz dodać warunek podobny do tego

(int)strcmp ((char*)object_getClassName ($R0), "NSString")= = 0

 4
Author: Jeff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-03 21:31:45

Jeśli chcesz logować metody w symulatorze na 64 bitach, użyj następującego polecenia:

expr -- (void) printf("[%s %s]\n", (char *)object_getClassName($rdi), (char *) $rsi)

Lub jeśli to nie działa, Zaloguj to w ten sposób:

Tutaj wpisz opis obrazka

Główną ideą jest użycie $RDI dla obiektu (self)i $RSI dla selektora.

 2
Author: TGO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 19:59:33

Kolega programista nauczył mnie dodawania tych samych dwóch poleceń dziennika do każdej metody. Jedna jako pierwsza linia, druga jako ostatnia linia. Myślę, że ma skrypt, który robi to automatycznie dla swoich projektów, ale wynik jest taki:

NSLog(@"<<< Entering %s >>>", __PRETTY_FUNCTION__);
NSLog(@"<<< Leaving %s >>>", __PRETTY_FUNCTION__);

Na konsoli to wypluje coś w stylu:

 <<< Entering -[MainListTableViewController viewDidLoad] >>>
Bardzo pomocne w śledzeniu tego, co się dzieje.
 1
Author: DenVog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-01 16:37:16