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?
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:
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.
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))
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)
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
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) )
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
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:
Główną ideą jest użycie $RDI dla obiektu (self)i $RSI dla selektora.
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.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