2013-03-20 2 views
24

Ho un punto di interruzione che assomiglia a questoCome ottenere i parametri utilizzando i punti di interruzione simbolici in Objective-C

-[UITableViewCell setSelected:] 

e funziona, ma non riesco a capire come ottenere il valore che viene passato in.

Ho provato -[UITableViewCell setSelected:(BOOL)what] e -[UITableViewCell setSelected:what] che non funzionano affatto.

Come accedere ai parametri?

Se questo non funziona, dovrò fare un DebugUITableViewCell solo per vedere cosa sta succedendo, che è una seccatura e tocca un sacco di codice.

+1

Non sono abbastanza coraggioso da postare questa risposta reale mentre sto solo speculando, ma credo che il desiderio non sia disponibile per il debugger. Non si ottengono i simboli per UIKit, quindi il debugger non ha idea qual è il nome dell'argomento per quel metodo, il runtime potrebbe essere in grado di capire il suo tipo, ma non è lo stesso che avere le informazioni reali sui simboli.Il trucco della sottoclasse funziona, immagino perché stai fornendo anche le informazioni sui simboli al debugger. –

risposta

26

Se si esegue il debug del codice sul dispositivo, i parametri quando si preme il punto di interruzione saranno costantemente nei registri r0, r1 e r2. Se usi po $r0 vedrai l'oggetto che riceve setSelected. Se usi po $r1 otterrai "nessuna descrizione Objective-C disponibile" perché quello è il selettore. Ispezionare $ r2 per vedere se selezionato è impostato su SÌ o NO. È una storia simile su i386, ma non riesco a ricordare a memoria quali registri sono usati.

+0

So che questo era un trucco ben utilizzato con gdb, ma credo che non funzionerà in modo coerente in lldb. –

+1

@darren Ho provato questo con lldb prima di postare la mia risposta, ma cosa ti fa pensare che non funzionerebbe? –

+9

Funzionerà bene con lldb. In effetti, è ancora meglio in lldb perché (per le architetture che passano gli argomenti nei registri, come arm e x86_64) '$ arg0',' $ arg1' ecc viene fornito quale alias al registro corretto per tale architettura. –

4

È possibile sostituire -[UITableViewCell setSelected:] con la propria implementazione per scopi di debug. Di seguito, verrà chiamato il numero UITableViewCellSetSelected invece del metodo 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

anche se per una soluzione rapida @ la risposta di aaron è buona. Lascerò questo qui per informazioni ... – nielsbot

+0

Penso che potrei accettare la risposta di Aaron perché è più sul punto, ma anche questo è grandioso. Grazie! –

7

In LLDB su Simulatore di utilizzare

p $arg3

per il primo parametro.

1

In base al simbolo -[UIApplication sendAction:toTarget:fromSender:forEvent:] è possibile aggiungere un punto di interruzione simbolico per verificare quale mittente ha inviato un'azione a quale destinazione.

Creiamo punto di interruzione simbolica con:

  • simbolo: -[UIApplication sendAction:toTarget:fromSender:forEvent:]
  • azioni della riga di comando del debugger:
    • po "Target"
    • po $arg4
    • po "Sender"
    • po $arg5

L'output sarà: "Target" <project.TargetViewController: 0x14ddb1470> "Sender" <UIButton: 0x14de86000; frame = (331 7; 49 30); opaque = NO; layer = <CALayer: 0x174237020>>

Così come detto @ Dan, parametri di metodo inizia con argomento 3 (po $arg3).