2012-04-20 14 views
7

Tengo un problema donde recibo excepciones de acceso incorrecto pero solo cuando ejecuto una compilación de prueba (llamar a los mismos métodos en una compilación de depuración no hace que surja el problema). El proyecto ha permitido ARC y me estoy quedando esto en el simulador de iPad 5,1 usando Xcode 4.3:EXC_BAD_ACCESS utilizando ARC solo durante las pruebas

Aquí es donde el problema surge:

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

En el punto cuando se llama al método addObserver: que doesn' Parece que cualquiera de los objetos involucrados debería haber sido lanzado, entonces ¿qué podría estar causando la excepción?

EDIT:

Disculpas si no estaba claro, pero el código de seguridad se ejecuta como parte de un caso de prueba (utilizando el estándar Xcode OCUnit). También en caso de que aclara nada aquí está el código correspondiente de la clase de jugador (hay otros Ivars y métodos, pero que no tienen ninguna conexión con la propiedad o los métodos que se está probando):

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

Respuesta

21

Si su clase es realmente compatible con los valores-clave, asegúrese de que la implementación para la clase que exhibe el problema no esté incluida en su producto de prueba. Esto significa que el panel de Membresía de Destino del inspector de Identidad para su archivo .m solo debe tener su aplicación marcada (no YourAppTests).

Tuve el mismo problema en Xcode 4.3.1 cuando se incluyó una implementación en ambos productos y registré observadores tanto en código de producción como de prueba. Los siguientes registros de mí alertados:

Clase YourClass se implementa en tanto/Soporte de Usuarios/yourUser/Library/Application Support/simulador de iPhone/5.1/Aplicaciones // YourApp.app/YourApp y/Usuarios/yourUser/Library/Desarrollador/Xcode/DerivedData/YourApp-/Build/Products/Debug-iphonesimulator/YourAppTests.octest/YourAppTests. Uno de los dos será usado. Cuál es indefinido

+3

Ojalá pudiera votar esto 100 veces. ¡Gracias! – DexterW

+0

También encontré este problema con CocoaPods. El archivo de implementación de la clase se incluyó en los pods para la aplicación y el objetivo de la prueba de la aplicación, excepto que no había una advertencia de clase duplicada en los registros. – Eric

0

Según el Key-Value Observing Programming Guide, se su jugador clave-valor-obediente? Desea asegurarse de que es Ensuring KVC Compliance. También asumo que usted también ha implementado su observeValueForKeyPath:ofObject:change:context:? Si cree que ha hecho todo esto y todavía no funciona, entonces quizás pueda compartir su código.

Además, algo menor, pero supongo que esto es un fragmento de código para resaltar el problema. Solo lo menciono porque ARC va a liberar su objeto p al final de su testChangeFoodNotification y habría pensado que primero querría eliminar a su observador.

+0

Gracias por la respuesta. Podría perderme algo, pero creo que la clase cumple con KVC (el hecho de que ese mismo código funcione fuera de una compilación de prueba me hace pensar que es compatible, pero puedo estar equivocado, esta es la primera vez que uso KVC/KVO). En cuanto a la eliminación del observador. Normalmente lo haría pero pensé que dado que este es un método de caso de prueba y tanto p como el observador van a ser destruidos antes de que haya alguna posibilidad de modificar p otra vez, sería mejor evitar complicar el método de prueba con repetitivo. Sin embargo, podría estar equivocado y si lo estoy, me encantaría saber cómo;) – Mattia

+0

Sí, no lo estoy viendo. Lo siento. No entiendo por qué está definiendo su interfaz privada para _food ni por qué escribe su propio setter (la declaración @synthesize hace ambas cosas por usted), pero duda de que ese sea el origen del problema. Más importante aún, no entiendo por qué obtienes un comportamiento diferente en las versiones de prueba v de depuración. Solo puedo sugerir que te cambies de zombies modificando tu esquema en tu versión de prueba, si no lo has hecho aún, y ve si es más esclarecedor. – Rob

+0

Originalmente no estaba agregando mis propios setters pero los agregué para ver si ese era el problema (pensé que tal vez los sintetizados no llamaran a will/didChangeValueForKey, ese no parece ser el caso). La razón por la que declaro mi propia variable privada es el hábito: me gustan mis ivars con guiones bajos y el compilador los sintetiza sin el guión bajo. En cualquier caso, gracias por echar un vistazo. – Mattia

Cuestiones relacionadas