Как установить условную точку останова в Xcode на основе свойства строки объекта?

93

Я ищу возможность прерывания отладчика при достижении определенного совпадения строки. В качестве примера у меня может быть что-то вроде этого:

Foo myObj = [self gimmeObj];

myObjможет иметь свойство под названием name. Я хочу, чтобы отладчик останавливал задание, когда

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

Как я могу установить условную точку останова в Xcode для этого?

Coocoo4Cocoa
источник

Ответы:

184

Вы можете установить условную точку останова в Xcode, установив точку останова в обычном режиме, затем щелкните ее, удерживая клавишу Control, и выберите «Изменить точку останова» (выберите «Выполнить» -> «Показать» -> «Точки останова»).

В записи точки останова есть столбец Условие.

Теперь есть несколько моментов, которые следует учитывать при этом условии. Во-первых, gdb не понимает синтаксис с точкой, поэтому вместо myObj.name вы должны использовать [myObj name] (если имя не является ivar).

Затем, как и в большинстве выражений в gdb, вы должны указать ему тип возвращаемого результата, а именно «BOOL». Итак, установите такое условие:

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

Часто на самом деле проще сделать это в коде, временно добавив такой код, как:

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

а затем установите точку останова в NSLog. Тогда ваше условие может быть произвольно сложным, не беспокоясь о том, что GDB может и что не может анализировать.

Питер Н. Льюис
источник
12
За исключением того, что, изменив свой код, вы рискуете забыть удалить свое ведение журнала или изменить поведение
Пол Браттберг,
3
Это правда. Я часто смягчаю это, добавляя к строке «NYI» (еще не реализовано), и тогда мой поиск NYI с проверкой перед выпуском обнаружит это.
Питер Н Льюис
18
Чтобы это заработало, мне пришлось сделать (bool) прописными буквами (BOOL), вероятно, это вещь LLDB.
Wex
1
bool не работал у меня в GDB, мне пришлось использовать BOOL или int - разница объясняется здесь stackoverflow.com/a/544250/725871 .
Chaosphere2112
2
Вы не можете поместить это в код, если у вас есть ошибка игры раз в 200, которая наконец-то возникла, и теперь вам нужно выполнить условную точку останова. Остановить программу для изменения кода нельзя.
Almo
21

Вот как вы используете условные точки останова XCode lldb.

Сначала дважды щелкните точку останова (или щелкните правой кнопкой мыши edit breakpoint), вы увидите всплывающее диалоговое окно.

введите описание изображения здесь

Вот что означает этот вариант:

  1. Условие : точка останова сработает только при этом условии.
  2. Игнорировать : количество раз, которое должно выполняться условие перед запуском точки останова.
  3. Действие : действие, которое выполняется после разрыва точки останова.
  4. Параметры : автоматически продолжить после оценки действий

Вот резюме. Для приведенного выше примера на изображении это означает, что, когда переменная buildingIdравна 13, остановитесь здесь. Если я добавлю время игнорирования к 1, тогда он будет игнорировать первый раз, когда buildingIdоно равно 13, и прервется во второй раз, когда условие выполнено.

Для действий, когда вы нажимаете добавить действия, появится список выбора. Обычно я использую Debugger Command poдля печати переменных, которые мне нужно проверить, и я считаю, что есть более эффективные способы использования действий, чем я.

Похоже, вам придется перекомпилировать и запустить приложение, если вы измените условия во время выполнения

Nuynait
источник
Вероятно, потому что вопрос был об остановке в точке останова на основе строкового значения [я не был противником]
ZS
1
Спасибо, очень полезно. Этот ответ заслуживает большего количества голосов.
andreskwan
7

Я не уверен, что это сработает, но вы можете попробовать установить точку останова в этой строке кода, открыть консоль отладчика (Cmd + Shift + R) и ввести

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

Где N заменяется номером точки останова (целым числом).

Адам Розенфилд
источник
2

Если вы изменяете myObj.name с помощью установщика, вы можете добавить символическую точку останова -[MyObjClass setName:]либо из консоли отладчика, либо из меню «Выполнить» -> «Управление точками останова» - > «Добавить символическую точку останова» в Xcode. Если нет (почему бы и нет? Вам, вероятно, не следует изменять переменную экземпляра напрямую, за исключением назначенного инициализатора или dealloc), вы можете установить точку наблюдения в gdb (используйте консоль отладчика в Xcode после запуска отладчика). Эта страница объясняет, как это сделать. Я не верю, что Xcode предоставляет пользовательский интерфейс для установки точек наблюдения без использования консоли отладчика.

Барри Уорк
источник
0

Иногда при работе с фреймворками (отладочные сборки) вам необходимо установить точку останова в определенном файле / месте, по которому трудно ориентироваться или который не отображается публично в разрабатываемой платформе. Один из вариантов - написать вспомогательный класс, чтобы запускать условные точки останова и упростить вход / выход.

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

Объявление заголовка в разрабатываемой структуре.

#import <Foundation/Foundation.h>

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

И файл реализации:

#import "DebugConditionalBreakPointHelper.h"

@implementation DebugConditionalBreakPointHelper
+ (void)breakPointCondition:(BOOL)enabled comment:(NSString *)comment {
    if (enabled)
    {
        NSLog(@"Triggerred Conditional Break Point. Comment: %@");
    }
}
@end
лал
источник