Wie setze ich einen bedingten Haltepunkt in Xcode basierend auf einer Objektzeichenfolgeeigenschaft?

90

Ich möchte in der Lage sein, den Debugger zu unterbrechen, wenn er eine bestimmte Zeichenfolgenübereinstimmung erreicht. Als Beispiel könnte ich so etwas haben:

Foo myObj = [self gimmeObj];

myObjkönnte eine Eigenschaft namens haben name. Ich möchte, dass der Debugger bei der Zuweisung stoppt, wenn

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

Wie kann ich dafür meinen bedingten Haltepunkt in Xcode festlegen?

Coocoo4Cocoa
quelle

Antworten:

184

Sie können einen bedingten Haltepunkt in Xcode festlegen, indem Sie den Haltepunkt normal einstellen, dann bei gedrückter Ctrl-Taste darauf klicken und Haltepunkt bearbeiten auswählen (wählen Sie Ausführen -> Anzeigen -> Haltepunkte).

Im Haltepunkteintrag befindet sich eine Bedingungsspalte.

Nun gibt es einige Probleme, die bei der Erkrankung zu beachten sind. Erstens versteht gdb die Punktsyntax nicht. Daher müssen Sie anstelle von myObj.name [myObj name] verwenden (es sei denn, name ist ein ivar).

Als nächstes müssen Sie, wie bei den meisten Ausdrücken in gdb, die Art des Rückgabeergebnisses angeben, nämlich "BOOL". Stellen Sie also eine Bedingung ein wie:

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

Oft ist es tatsächlich einfacher, dies einfach im Code zu tun, indem vorübergehend Code hinzugefügt wird wie:

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

und dann den Haltepunkt auf dem NSLog einstellen. Dann kann Ihr Zustand beliebig komplex sein, ohne sich Gedanken darüber machen zu müssen, was GDB analysieren kann und was nicht.

Peter N Lewis
quelle
11
Abgesehen davon, dass Sie durch Ändern Ihres Codes das Risiko
eingehen, zu
3
Das ist richtig. Ich mildere dies oft ab, indem ich der Zeichenfolge "NYI" (noch nicht implementiert) hinzufüge, und dann wird meine Suche nach NYI vor der Veröffentlichung es abfangen.
Peter N Lewis
17
Um dies zum Laufen zu bringen, musste ich (bool) als (BOOL) in Großbuchstaben schreiben, wahrscheinlich eine LLDB-Sache.
Wex
1
bool hat bei mir in GDB nicht funktioniert, ich musste BOOL oder int verwenden - der Unterschied wird hier erklärt stackackflow.com/a/544250/725871 .
Chaosphere2112
2
Sie können es nicht in den Code einfügen, wenn Sie alle 200 Spiele einen Fehler haben, der endlich aufgetreten ist, und jetzt müssen Sie einen bedingten Haltepunkt erstellen. Das Stoppen des Programms zum Ändern des Codes ist keine Option.
Almo
17

Hier erfahren Sie, wie Sie bedingte XCode lldb-Haltepunkte verwenden.

Doppelklicken Sie zunächst auf den Haltepunkt (oder klicken edit breakpointSie mit der rechten Maustaste ). Daraufhin wird ein Dialogfeld angezeigt.

Geben Sie hier die Bildbeschreibung ein

Diese Option bedeutet Folgendes:

  1. Bedingung : Der Haltepunkt wird nur unter dieser Bedingung ausgelöst.
  2. Ignorieren : Die Häufigkeit, mit der die Bedingung erfüllt sein muss, bevor der Haltepunkt ausgelöst wird
  3. Aktion : Aktion, die ausgeführt wird, nachdem der Haltepunkt unterbrochen wurde.
  4. Optionen : Nach Auswertung der Aktionen automatisch fortfahren

Hier ist eine Zusammenfassung. Für das obige Beispiel im Bild bedeutet dies, dass Sie buildingIdhier brechen , wenn die Variable gleich 13 ist. Wenn ich die Ignorierzeit zu 1 addiere, wird das erste Mal ignoriert, wenn buildingIdes gleich 13 ist, und beim zweiten Mal, wenn die Bedingung erfüllt ist, unterbrochen.

Wenn Sie für Aktionen auf Aktionen hinzufügen klicken, wird eine Liste mit Auswahlmöglichkeiten angezeigt. Normalerweise verwende ich die Debugger Command pozum Drucken von Variablen, die ich überprüfen muss, und ich glaube, dass es bessere Möglichkeiten gibt, die Aktionen zu verwenden als ich.

Es scheint, dass Sie die App neu kompilieren und ausführen müssen, wenn Sie die Bedingungen zur Laufzeit ändern

nuynait
quelle
Wahrscheinlich, weil es um das Anhalten am Haltepunkt ging, basierend auf einem String-Wert [Ich war nicht der Down-Voter]
ZS
1
Danke, sehr hilfreich. Diese Antwort verdient mehr Stimmen.
Andreskwan
7

Ich bin nicht sicher, ob dies funktionieren wird, aber Sie können versuchen, einen Haltepunkt in dieser Codezeile festzulegen, die Debugger-Konsole (Cmd + Shift + R) öffnen und eingeben

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

Dabei wird N durch die Nummer des Haltepunkts (eine Ganzzahl) ersetzt.

Adam Rosenfield
quelle
2

Wenn Sie myObj.name mit dem Setter mutieren, können Sie einen symbolischen Haltepunkt -[MyObjClass setName:]entweder über die Debugger-Konsole oder über das Menü Ausführen-> Haltepunkte verwalten-> Symbolischen Haltepunkt hinzufügen in Xcode hinzufügen. Wenn nicht (warum nicht? Sie sollten die Instanzvariable wahrscheinlich nicht direkt ändern, außer im angegebenen Initialisierer oder Dealloc), können Sie einen Überwachungspunkt in gdb festlegen (verwenden Sie die Debugger-Konsole in Xcode, sobald der Debugger ausgeführt wird). Diese Seite erklärt wie. Ich glaube nicht, dass Xcode eine Benutzeroberfläche zum Festlegen von Überwachungspunkten ohne Verwendung der Debugger-Konsole bereitstellt.

Barry Wark
quelle
0

Manchmal, wenn mit Frameworks gearbeitet wird (Debug-Builds) und ein Haltepunkt in einer bestimmten Datei / einem bestimmten Speicherort eingefügt werden muss, der schwer zu navigieren ist oder in dem in der Entwicklung befindlichen Framework nicht öffentlich verfügbar gemacht wird. Eine Möglichkeit besteht darin, eine Hilfsklasse zu schreiben, um bedingte Haltepunkte auszulösen und das Ein- und Aussteigen zu vereinfachen.

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

Header-Deklaration im Framework in Entwicklung.

#import <Foundation/Foundation.h>

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

Und Implementierungsdatei:

#import "DebugConditionalBreakPointHelper.h"

@implementation DebugConditionalBreakPointHelper
+ (void)breakPointCondition:(BOOL)enabled comment:(NSString *)comment {
    if (enabled)
    {
        NSLog(@"Triggerred Conditional Break Point. Comment: %@");
    }
}
@end
lal
quelle