2013-03-20 4 views
24

Mam przerwania, który wygląda takJak uzyskać parametry przy użyciu punktów przerwania symboliczne w Objective-C

-[UITableViewCell setSelected:] 

i to działa, ale nie mogę dowiedzieć się, jak uzyskać wartość, która jest przekazywana w.

Próbowałem -[UITableViewCell setSelected:(BOOL)what] i -[UITableViewCell setSelected:what], które nie działają w ogóle.

Jak uzyskać dostęp do parametrów?

Jeśli to nie zadziała, będę musiał zrobić DebugUITableViewCell tylko po to, aby zobaczyć, co się dzieje, co jest kłopotliwe i dotyka dużo kodu.

+1

Nie jestem na tyle odważny, aby opublikować tę prawdziwą odpowiedź, ponieważ właśnie spekuluję, ale uważam, że nie jest dostępna dla debuggera. Nie otrzymujesz symboli UIKit, więc debugger nie ma pojęcia o jaka jest nazwa argumentu dla tej metody, środowisko wykonawcze może być w stanie określić jego typ, ale nie jest tożsame z posiadaniem prawdziwej informacji o symbolu.Twoja sztuczka podklasy działa, jak sądzę, ponieważ dostarczasz informacje o tym symbolu do debuggera. –

Odpowiedz

26

W przypadku debugowania kodu na urządzeniu parametry po trafieniu punktu przerwania będą konsekwentnie znajdować się w rejestrach r0, r1 i r2. Jeśli użyjesz po $r0 zobaczysz obiekt otrzymujący setSelected. Jeśli użyjesz po $r1, otrzymasz "brak opisu w Objective-C", ponieważ jest to selektor. Sprawdź $ r2, aby sprawdzić, czy wybrano opcję TAK lub NIE. To jest podobna historia na i386, ale nie pamiętam z ręki, które rejestry są używane.

+0

Wiem, że był to dobrze wykorzystany trik z gdb, ale uważam, że nie będzie działać konsekwentnie w lldb. –

+1

@darren Testowałem to z lldb przed opublikowaniem mojej odpowiedzi, ale co sprawia, że ​​myślisz, że to nie zadziała? –

+9

Będzie działać dobrze z lldb. W rzeczywistości jest jeszcze lepiej w lldb, ponieważ (w architekturach, które przekazują argumenty w rejestrach, takich jak arm i x86_64) podane są '$ arg0',' $ arg1' itp, które są aliasami do poprawnego rejestru dla tej architektury. –

4

Możesz zastąpić -[UITableViewCell setSelected:] swoją własną implementacją do celów debugowania. Poniżej zostanie wywołana UITableViewCellSetSelected zamiast metody UIKit.

static void (*__originalUITableViewCellSetSelected)(UITableViewCell *, SEL, BOOL) ; 
static void UITableViewCellSetSelected(UITableViewCell * self, SEL _cmd, BOOL b) 
{ 
    // your code here... (or set a breakpoint here) 
    NSLog(@"%@<%p> b=%s\n", [ self class ], self, b ? "YES" : "NO") ; 

    (*__originalUITableViewCellSetSelected)(self, _cmd, b) ; // call original implementation: 
} 

@implementation UITableViewCell (DebugIt) 

+(void)load 
{ 
    Method m = class_getInstanceMethod([ self class ], @selector(setSelected:)) ; 
    __originalUITableViewCellSetSelected = (void(*)(id, SEL, BOOL))method_getImplementation(m) ; 
    method_setImplementation(m, (IMP)UITableViewCellSetSelected) ; 
} 

@end 
+0

Chociaż dla szybkiego rozwiązania, odpowiedź Aarona jest dobra. Zostawię to tutaj dla informacji ... – nielsbot

+0

Myślę, że mogę zaakceptować odpowiedź Aarona, ponieważ jest to bardziej celne, ale to też jest świetne. Dziękuję Ci! –

7

W LLDB na symulatorze użyć

p $arg3

dla pierwszego parametru.

1

Na podstawie symbolu -[UIApplication sendAction:toTarget:fromSender:forEvent:] możemy dodać symboliczny punkt przerwania, aby sprawdzić, który nadawca wysłał czynność, do której ma trafić.

Tworzymy symboliczne przerwania z:

  • Symbol: -[UIApplication sendAction:toTarget:fromSender:forEvent:]
  • debugera działań Wiersz poleceń:
    • po "Target"
    • po $arg4
    • po "Sender"

Wyjście to: "Target" <project.TargetViewController: 0x14ddb1470> "Sender" <UIButton: 0x14de86000; frame = (331 7; 49 30); opaque = NO; layer = <CALayer: 0x174237020>>

@Dan Tak więc, że parametry metody początek argumentu 3 (po $arg3).