web-dev-qa-db-fra.com

Comment définir un point d'arrêt conditionnel dans Xcode en fonction d'une propriété de chaîne d'objet?

Je cherche à pouvoir avoir le débogueur cassé quand il atteint une correspondance de chaîne particulière. Par exemple, je pourrais avoir quelque chose comme ça:

Foo myObj = [self gimmeObj];

myObj pourrait avoir une propriété appelée name. Je veux que le débogueur s'arrête sur l'affectation quand

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

Comment définir mon point d'arrêt conditionnel dans Xcode?

83
Coocoo4Cocoa

Vous pouvez définir un point d'arrêt conditionnel dans Xcode en le définissant normalement, puis cliquez dessus en maintenant la touche Ctrl enfoncée, puis sélectionnez Modifier le point d'arrêt (choisissez Exécuter -> Afficher -> Points d'arrêt).

Dans l'entrée du point d'arrêt, il y a une colonne Condition.

Maintenant, il y a plusieurs problèmes à garder à l'esprit pour la condition. Tout d'abord, gdb ne comprend pas la syntaxe des points. Au lieu de myObj.name, vous devez utiliser [myObj name] (sauf si name est un ivar).

Ensuite, comme avec la plupart des expressions de gdb, vous devez lui indiquer le type de résultat renvoyé, à savoir "BOOL". Donc fixez une condition comme:

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

Il est souvent plus facile de faire cela dans le code en ajoutant temporairement du code comme:

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

puis en définissant le point de rupture sur le NSLog. Ensuite, votre condition peut être arbitrairement complexe sans avoir à vous soucier de ce que gdb peut et ne peut pas analyser.

173
Peter N Lewis

Voici comment utiliser les points d'arrêt conditionnels XCode lldb.

Tout d’abord, double-cliquez sur le point de rupture (ou cliquez avec le bouton droit sur edit breakpoint) pour afficher une boîte de dialogue.

 enter image description here

Voici ce que ces options signifient:

  1. Condition: le point d'arrêt ne se déclenchera que dans cette condition.
  2. Ignore: le nombre de fois que la condition doit être remplie avant de déclencher le point d'arrêt
  3. Action: action exécutée après la rupture du point d'arrêt.
  4. Options: Continuer automatiquement après l'évaluation des actions

Voici un résumé. Pour l'exemple ci-dessus dans l'image, cela signifie que lorsque la variable buildingId est égale à 13, séparez-la ici. Si j'ajoute ignorer le temps à 1, il ignorera la première fois lorsque buildingId est égal à 13 et se cassera à la deuxième fois que la condition est remplie. 

Pour les actions, lorsque vous appuyez sur ajouter des actions, il y aura une liste de choix. Habituellement, ce que je fais est d’utiliser la Debugger Commandpo pour imprimer les variables que j’ai besoin de vérifier et j’estime qu’il existe de meilleures façons d’utiliser les actions que je le fais.

Il semble que vous deviez recompiler et exécuter l'application si vous modifiez les conditions à l'exécution

9
nuynait

Je ne sais pas si cela fonctionnera, mais vous pouvez essayer de définir un point d'arrêt sur cette ligne de code, d'ouvrir la console du débogueur (Cmd + Maj + R) et de taper

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

Où N est remplacé par le numéro du point d'arrêt (un entier).

7
Adam Rosenfield

Si vous modifiez myObj.name à l'aide du setter, vous pouvez ajouter un point d'arrêt symbolique sur -[MyObjClass setName:] à partir de la console du débogueur ou du menu Exécuter-> Gérer les points d'arrêt-> Ajouter un point d'arrêt symbolique dans Xcode. Si ce n'est pas le cas (pourquoi pas? Vous ne devriez probablement pas modifier la variable d'instance directement, sauf dans l'initialiseur désigné ou dealloc), vous pouvez définir un point de contrôle dans gdb (utilisez la console du débogueur dans Xcode une fois le débogueur exécuté). Cette page explique comment. Je ne crois pas que Xcode expose une interface utilisateur pour la configuration de points de contrôle sans utiliser la console du débogueur.

2
Barry Wark

Parfois, lorsque vous travaillez avec Frameworks (versions de débogage) et que vous devez placer un point d'arrêt dans un fichier/emplacement difficile à naviguer ou exposé publiquement dans une structure en développement. Une option consiste à écrire une classe d'assistance pour déclencher des points d'arrêt conditionnels et faciliter l'intégration/la suppression progressive.

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

Déclaration d'en-tête dans le cadre en développement.

#import <Foundation/Foundation.h>

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

Et fichier d'implémentation:

#import "DebugConditionalBreakPointHelper.h"

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