2012-04-20 2 views
7

У меня проблема, когда у меня возникают исключения для доступа, но только при запуске тестовой сборки (вызов тех же методов в сборке отладки не вызывает проблемы). Проект включен ARC, и я бегу это на IPad 5.1 тренажере с использованием Xcode 4.3:EXC_BAD_ACCESS с использованием ARC только во время тестирования

Вот где проблема выплывает:

- (void)testChangeFoodNotification { 
    Player* p = [[Player alloc] init]; 
    [p addObserver:self forKeyPath:@"food" options:0 context:0]; // <-EXC_BAD_ACCESS (code=2) 
    p.food += 1; 
    STAssertTrue(_wasNotifiedOfFoodChange, nil); 
} 

В тот момент, когда метод addObserver: называется Безразлично» Кажется, что какой-либо из задействованных объектов должен был быть выпущен, так что может вызвать исключение?

РЕДАКТИРОВАТЬ:

Извинения, если это не было ясно, но выше код выполняется как часть теста (с использованием стандартного Xcode OCUnit). Кроме того, в случае проясняет ничего здесь соответствующий код из класса игрока (есть другие Ивар и методы, но они не имеют никакого отношения к собственности или методам тестируются):

// Public interface 
@interface Player : NSObject 

@property (nonatomic, assign) NSInteger food; 

@end 

// Private interface 
@interface Player() { 
    NSInteger _food; 
} 

@end 

@implementation Player 

@synthesize food = _food; 

#pragma mark - Getters/Setters 

- (void)setFood:(NSInteger)food { 
    [self willChangeValueForKey:@"food"]; 
    _food = food; 
    [self didChangeValueForKey:@"food"];  
} 

ответ

21

Если ваш класс действительно совместим с ключевыми значениями, убедитесь, что реализация класса, в котором указан этот вопрос, не включена в тестовый продукт. Это означает, что в панели целевого членства инспектора удостоверений для вашего файла .m должно быть проверено только ваше приложение (а не YourAppTests).

Я испытал ту же проблему в Xcode 4.3.1, когда реализация была включена в оба продукта, и я зарегистрировал наблюдателей как в производственном, так и в тестовом кодах. Следующие журналы наконечниками меня:

Класс YourClass осуществляется в обоих/Поддержка пользователей/yourUser/Library/Application/iPhone Simulator/5,1/Применения // YourApp.app/YourApp и/Users/yourUser/Library/Разработчик/Xcode/DerivedData/YourApp-/сборки/Продукты/Debug-iphonesimulator/YourAppTests.octest/YourAppTests. Один из двух будет использован. Какой из них не определен.

+3

Жаль, что я не смог бы поддержать это 100 раз. Благодаря! – DexterW

+0

Я также столкнулся с этой проблемой с CocoaPods. Файл реализации класса был включен в контейнеры для целевого объекта приложения и приложения, за исключением того, что в журналах не было повторяющегося предупреждения класса. – Eric

0

Согласно Key-Value Observing Programming Guide, является ваш игрок имеет ключевое значение? Вы хотите, чтобы вы были Ensuring KVC Compliance. Я также предполагаю, что вы также внедрили свой observeValueForKeyPath:ofObject:change:context:? Если вы думаете, что сделали все это, и он все еще не работает, возможно, вы можете поделиться своим кодом.

Кроме того, незначительная вещь, но я предполагаю, что это фрагмент кода, чтобы выделить проблему. Я только упоминаю об этом, потому что ARC собирается освободить ваш объект p в конце вашего testChangeFoodNotification, и я подумал бы, что вы хотите сначала удалить своего наблюдателя.

+0

Благодарим за отзыв. Я мог бы что-то упустить, но я думаю, что класс соответствует KVC (тот факт, что этот же код работает за пределами тестовой сборки, заставляет меня думать, что это совместимо, но я могу ошибаться - это мой первый раз, когда я использую KVC/KVO). Что касается удаления наблюдателя. Обычно я хотел бы, но я решил, что, поскольку это метод тестового случая, и как p, так и наблюдатель будут уничтожены до того, как будет возможность изменить p снова, было бы лучше избегать загромождения метода тестирования с помощью шаблона. Я мог бы ошибаться, хотя и если бы я был бы рад услышать, как;) – Mattia

+0

Да, я этого не вижу. Сожалею. Я не понимаю, почему вы определяете свой частный интерфейс для _food и почему вы пишете свой собственный сеттер (оператор @synthesize делает оба из них для вас), но сомневаюсь, что это источник проблемы. Что еще более важно, я не понимаю, почему вы получаете другое поведение в тестах debug v. Я могу только предложить вам включить зомби, изменив вашу схему в вашей тестовой сборке, если вы еще этого не сделали, и посмотрите, насколько она более просветляющая. – Rob

+0

Первоначально я не добавлял свои собственные сеттеры, но я добавил их, чтобы посмотреть, была ли эта проблема (я подумал, что, возможно, синтезированные из них не вызывали will/didChangeValueForKey - это, похоже, не так). Причина, по которой я объявляю свою собственную переменную, - это привычка: мне нравятся мои ivars с подчеркиваниями, а компилятор синтезирует их без подчеркивания. В любом случае спасибо, что посмотрели. – Mattia