2012-04-20 25 views
7

Mam problem, w którym dostaję złych wyjątków dostępu, ale tylko podczas uruchamiania kompilacji testowania (wywoływanie tych samych metod w kompilacji debugowania nie powoduje problemu). Projekt ARC włączona i biegnę to na symulatorze iPad 5.1 wykorzystaniem Xcode 4.3:EXC_BAD_ACCESS przy użyciu ARC tylko podczas testów

Oto gdzie problem crops up:

- (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); 
} 

W momencie gdy metoda addObserver: nazywa się to robi” Wygląda na to, że jakikolwiek z zaangażowanych obiektów powinien zostać zwolniony, co może być przyczyną wyjątku?

Edycja:

Przeproszenia gdyby nie było jasne, ale powyższy kod jest wykonywany jako część testu (stosując standardowe Xcode OCUnit). Również w przypadku wyjaśnia coś tu jest odpowiedni kod z klasy odtwarzacza (tam inne Ivars i metod, ale one nie mają żadnego połączenia do właściwości lub metody w fazie testów):

// 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"];  
} 

Odpowiedz

21

Jeśli twoja klasa jest rzeczywiście zgodna z kluczem wartości, upewnij się, że implementacja klasy wykazującej problem nie jest zawarta w testowanym produkcie. Oznacza to, że panel Docelowy członek inspektora tożsamości dla pliku .m powinien mieć zaznaczoną aplikację (nie YourAppTests).

Doświadczyłem tego samego problemu w Xcode 4.3.1, gdy implementacja została uwzględniona w obu produktach, a ja zarejestrowałem obserwatorów zarówno w kodzie produkcyjnym, jak i testowym. Poniższe dzienniki poradzili mi:

Klasa YourClass jest realizowany w obu/Pomoc Użytkownicy/yourUser/Library/Application/iPhone Simulator/5.1/Applications // YourApp.app/YourApp i/Users/yourUser/Library/Programista/Xcode/DerivedData/YourApp-/Build/Products/Debug-iphonesimulator/YourAppTests.octest/YourAppTests. Jeden z dwóch będzie użyty. Która z nich jest niezdefiniowana.

+3

Chciałbym móc to zrobić 100 razy. Dzięki! – DexterW

+0

Też napotkałem ten problem z CocoaPods. Plik implementacji klas został uwzględniony w zasobnikach zarówno w celu testowania aplikacji, jak i aplikacji, z tym że w dziennikach nie było ostrzeżenia o zduplikowanej klasie. – Eric

0

Jak na Key-Value Observing Programming Guide jest Twoja zgodna z kluczem wartości Player? Chcesz się upewnić, że jesteś Ensuring KVC Compliance. Zakładam również, że zaimplementowałeś również swój observeValueForKeyPath:ofObject:change:context:? Jeśli uważasz, że zrobiłeś to wszystko i nadal nie działa, być może możesz udostępnić swój kod.

Poza tym, ale zakładam, że jest to fragment kodu, aby podkreślić problem. Wspominam o tym tylko dlatego, że ARC zamierza zwolnić twój obiekt p po zakończeniu testChangeFoodNotification i pomyślałbym, że najpierw chciałbyś usunąć swojego obserwatora.

+0

Dzięki za odpowiedź. Mogę czegoś nie zauważyć, ale myślę, że klasa jest zgodna z KVC (fakt, że ten sam kod działa poza testową kompilacją sprawia, że ​​myślę, że jest zgodny, ale mogę się mylić - to mój pierwszy raz przy użyciu KVC/KVO). Co do usuwania obserwatora. Normalnie chciałbym, ale pomyślałem, że skoro jest to metoda przypadku testowego i zarówno p, jak i obserwator zostaną zniszczone, zanim pojawi się jakakolwiek szansa na modyfikację p, lepiej byłoby uniknąć zaśmiecania metody testowej za pomocą bojlera. Mogę się mylić, a jeśli tak, to chciałbym usłyszeć jak;) – Mattia

+0

Tak, nie widzę tego. Przepraszam. Nie rozumiem, dlaczego definiujesz swój prywatny interfejs dla _food i dlaczego piszesz własnego setera (instrukcja @synthesize wykonuje obie te czynności dla ciebie), ale wątpliwości są źródłem problemu. Co ważniejsze, nie rozumiem, dlaczego masz inne zachowanie w testach wersji v debugowania. Mogę tylko zasugerować, aby włączyć zombie, modyfikując swój schemat w swojej wersji testowej, jeśli jeszcze tego nie zrobiłeś i sprawdź, czy jest bardziej pouczający. – Rob

+0

Początkowo nie dodawałem własnych seterów, ale dodałem je, aby zobaczyć, czy to był problem (myślę, że być może syntetyzowane nie wywoływały polecenia will/didChangeValueForKey - tak się nie dzieje). Powodem, dla którego deklaruję własną zmienną prywatną, jest nawyk: Lubię moje ivars z podkreśleniami, a kompilator syntetyzuje je bez podkreślenia. W każdym razie dzięki za spojrzenie. – Mattia

Powiązane problemy