Come impostare un punto di interruzione condizionale in Xcode basato su una proprietà della stringa di un oggetto?


90

Sto cercando di essere in grado di interrompere il debugger quando raggiunge una particolare corrispondenza di stringa. Ad esempio, potrei avere qualcosa del genere:

Foo myObj = [self gimmeObj];

myObjpotrebbe avere una proprietà chiamata name. Voglio che il debugger si fermi sull'assegnazione quando

[myObj.name isEqualToString:@"Bar"];

Come posso impostare il mio punto di interruzione condizionale in Xcode per farlo?

Risposte:


184

Puoi impostare un punto di interruzione condizionale in Xcode impostando normalmente il punto di interruzione, quindi fai clic tenendo premuto il tasto Ctrl su di esso e seleziona Modifica punto di interruzione (scegli Esegui -> Mostra -> Punti di interruzione).

Nella voce del punto di interruzione, è presente una colonna Condizione.

Ora, ci sono diversi problemi da tenere a mente per la condizione. In primo luogo, gdb non comprende la sintassi dei punti, quindi invece di myObj.name, devi usare [myObj name] (a meno che name non sia un ivar).

Successivamente, come con la maggior parte delle espressioni in gdb, è necessario indicare il tipo di risultato restituito, ovvero "BOOL". Quindi imposta una condizione come:

(BOOL)[[myObj name] isEqualToString:@"Bar"]

Spesso in realtà è più semplice farlo nel codice aggiungendo temporaneamente codice come:

if ( [myObj.name isEqualToString:@"Bar"] ) {
    NSLog( @"here" );
}

e quindi impostare il punto di interruzione su NSLog. Quindi la tua condizione può essere arbitrariamente complessa senza doversi preoccupare di ciò che gdb può e non può analizzare.


11
Tranne che alterando il tuo codice corri il rischio di dimenticare di rimuovere il tuo comportamento di registrazione o alterazione
Pål Brattberg

3
È vero. Spesso mitigo questo problema aggiungendo "NYI" (Not Yet Implemented) alla stringa, quindi la mia ricerca di controllo pre-rilascio per NYI lo rileverà.
Peter N Lewis

17
Per farlo funzionare ho dovuto scrivere (bool) maiuscolo come (BOOL), probabilmente una cosa LLDB.
Wex

1
bool non ha funzionato per me in GDB, ho dovuto usare BOOL o int - la differenza è spiegata qui stackoverflow.com/a/544250/725871 .
Chaosphere 2112

2
Non puoi metterlo in codice se hai un bug di gioco una volta ogni 200 che è finalmente emerso, e ora devi fare un breakpoint condizionale. Fermare il programma per modificare il codice non è un'opzione.
Almo

17

Ecco come utilizzare i punti di interruzione condizionali XCode lldb.

Innanzitutto, fai doppio clic sul punto di interruzione (o fai clic con il pulsante destro del mouse edit breakpoint), puoi vedere una finestra di dialogo popup.

inserisci qui la descrizione dell'immagine

Ecco cosa significano queste opzioni:

  1. Condizione : il punto di interruzione si attiverà solo in questa condizione.
  2. Ignora : il numero di volte che la condizione deve soddisfare prima di attivare il punto di interruzione
  3. Azione : azione eseguita dopo l'interruzione del punto di interruzione.
  4. Opzioni : continua automaticamente dopo aver valutato le azioni

Ecco una sintesi. Per l'esempio precedente nell'immagine, significa che quando la variabile buildingIdè uguale a 13, interrompi qui. Se aggiungo ignora tempo a 1, ignorerà la prima volta quando buildingIdè uguale a 13 e si interromperà la seconda volta che la condizione è soddisfatta.

Per le azioni, quando si preme aggiungi azioni, verrà visualizzato un elenco di scelte. Di solito quello che faccio è usare il fileDebugger Command po per stampare le variabili che devo controllare e credo che ci siano modi migliori di usare le azioni rispetto a me.

Sembra che tu debba ricompilare ed eseguire l'app se modifichi le condizioni in fase di esecuzione


Probabilmente perché la domanda riguardava l'arresto al punto di interruzione in base a un valore di stringa [non ero il votante negativo]
ZS

1
Grazie, molto utile. Questa risposta merita più voti.
andreskwan

7

Non sono sicuro che funzionerà, ma puoi provare a impostare un punto di interruzione su quella riga di codice, aprire la console del debugger (Cmd + Maiusc + R) e digitare

condition N (int)[[myObj name] isEqualToString:@"Bar"]

Dove N è sostituito dal numero del punto di interruzione (un numero intero).


2

Se si modifica myObj.name utilizzando il setter, è possibile aggiungere un punto di interruzione simbolico -[MyObjClass setName:]dalla console del debugger o dal menu Esegui-> Gestisci punti di interruzione-> Aggiungi punto di interruzione simbolico in Xcode. In caso contrario (perché no? Probabilmente non dovresti modificare la variabile di istanza direttamente tranne che nell'inizializzatore o dealloc designato) puoi impostare un punto di controllo in gdb (usa la console del debugger in Xcode una volta che il debugger è in esecuzione). Questa pagina spiega come. Non credo che Xcode esponga un'interfaccia utente per l'impostazione dei punti di controllo senza utilizzare la console del debugger.


0

A volte quando si lavora con Frameworks (build di debug) e è necessario inserire un punto di interruzione in un determinato file / posizione che è difficile da navigare o non è esposto pubblicamente nel framework in fase di sviluppo. Un'opzione è scrivere una classe helper per attivare i punti di interruzione condizionali e rendere più facile il passaggio all'ingresso / uscita.

- (void)invokeFrameworkMethod {
    ...
    [DebugConditionalBreakPointHelper breakPointCondition:YES comment:@"from invokeFrameworkMethod."];
    ...
}

Dichiarazione di intestazione nel quadro in fase di sviluppo.

#import <Foundation/Foundation.h>

@interface DebugConditionalBreakPointHelper : NSObject
+ (void)breakPointCondition:(BOOL)enabled comment:(NSString *)comment;
@end

E file di implementazione:

#import "DebugConditionalBreakPointHelper.h"

@implementation DebugConditionalBreakPointHelper
+ (void)breakPointCondition:(BOOL)enabled comment:(NSString *)comment {
    if (enabled)
    {
        NSLog(@"Triggerred Conditional Break Point. Comment: %@");
    }
}
@end
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.