objective-c xcode cocoa macos

objective c - Class Foo se implementa tanto en MyApp como en MyAppTestCase. Uno de los dos será usado. Cuál es indefinido



objective-c xcode (5)

Class Foo se implementa tanto en MyApp como en MyAppTestCase. Uno de los dos será usado. Cuál es indefinido

Me pregunto, ¿por qué es así?

porque ambas imágenes (la aplicación y el paquete de prueba de la unidad) definen la implementación de la clase. la clase se carga dinámicamente en el tiempo de ejecución objc. el tiempo de ejecución de objc usa un espacio de nombre plano. cómo funciona esto:

  • el binario está cargado, comenzando con sus dependencias
  • a medida que se carga cada binario, las clases objc se registran con el tiempo de ejecución objc
  • si una clase con un nombre específico se carga dos veces, el comportamiento no está definido. una implementación de una clase (con nombres idénticos) se puede cargar en el tiempo de ejecución objc.

el problema típico aquí es que se le devolverá una implementación: es probable que su aplicación falle cuando el tipo entra en conflicto (cuando la clase no proviene del mismo archivo fuente).

normalmente evita esto al cambiar el nombre de una clase o exportar la clase en una imagen. renombrar la clase obviamente no se aplica a su caso. tiene un archivo Foo.m que está siendo compilado, exportado y cargado por dos imágenes cuando debería estar en uno.

esto debe ser interpretado por usted como un error de vinculador de símbolo duplicado. aunque la implementación es el mismo archivo fuente (y la implementación es la misma): este es un problema que debe solucionar.

¿Como puedo resolver esto?

si Foo.m es una clase de la aplicación, debe eliminar (no compilar y vincular) Foo.m de la prueba unitaria. si es parte de la prueba de la unidad, no la compile y vincule con el objetivo de prueba de la unidad.

luego, siga las instrucciones en la publicación para vincular / cargar su prueba unitaria a la aplicación. está en esta área general de la publicación: donde "WhereIsMyMac" es el nombre de la aplicación que está probando por unidad. Esto permitirá que el objetivo de la prueba se vincule con la aplicación (por lo que no obtendrá errores del enlazador al compilar). la parte importante es que los archivos de prueba se compilan en el objetivo de la prueba de la unidad (solo) y las clases de la aplicación se compilan y se vinculan a la aplicación. no puedes simplemente agregarlos, se vinculan y se cargan dinámicamente.

Tal vez me perdí algo cuando establecí el objetivo de la prueba de unidad?

Del artículo que vinculó:

Nota: El objetivo de prueba es un objetivo separado. Esto significa que debe tener cuidado con la membresía objetivo. Todos los archivos fuente de la aplicación deben agregarse únicamente al objetivo de la aplicación. Los archivos de códigos de prueba se deben agregar solo al objetivo de prueba.

la parte que te equivocaste es probablemente las fases de enlace y carga del paquete de prueba de la unidad.

Recientemente comencé a probar mi aplicación. Este proyecto (en Xcode4) se creó sin un paquete de prueba unitario, así que tuve que configurarlo. He seguido los pasos desde aquí: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html Y estaba funcionando bien para las clases simples, pero ahora estoy tratando de probar una clase que depende en otro y eso en otro, etc.

Primero recibí un error del enlazador, así que agregué archivos *.m al objetivo del caso de prueba, pero ahora recibo una advertencia para cada clase que intento probar:

Class Foo se implementa tanto en MyApp como en MyAppTestCase. Uno de los dos será usado. Cuál es indefinido

Me pregunto, ¿por qué es así? ¿Como puedo resolver esto? Tal vez me perdí algo cuando establecí el objetivo de la prueba de unidad?

Editar - La solución

  • Establezca "Bundle Loader" correctamente en $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Establezca "Símbolos ocultos por defecto" en NO (en Configuración de compilación de la aplicación de destino). Aquí es de donde provienen los errores del enlazador porque es SÍ por defecto. ¡He estado luchando con esto por tanto tiempo !.

Fuente: ¿ Error de enlace para pruebas unitarias con XCode 4?


La razón es que anulas RUNPATH_SEARCH_PATHS de la RUNPATH_SEARCH_PATHS de RUNPATH_SEARCH_PATHS de tu aplicación definida en otro objetivo.

Solución:

Vaya a su destino de aplicación y busque la RUNPATH_SEARCH_PATHS compilación RUNPATH_SEARCH_PATHS y use el indicador $(inherited) para ambos: Depurar y liberar


Para mí, esto sucedió porque me desplegué en el dispositivo y luego en el simulador ya que tengo NSZombies habilitado. La solución fue cambiar a la configuración del simulador y hacer un Producto -> Limpiar, luego cambiar a la configuración del dispositivo y hacer lo mismo. El error desapareció Tiene que ver con la memoria caché de compilación.


Para mí, todo lo que tenía que hacer era desmarcar la casilla de verificación que hace que la clase Foo sea miembro del objetivo de prueba de la unidad. No debería ser un miembro de ambos objetivos, y debería verse así:

En caso de que no pueda ver la imagen, se trata de una captura de pantalla del panel "Membresía de destino" de Xcode. Hay dos objetivos: uno con un ícono de aplicación "A" y el nombre de la prueba. El otro es el objetivo de la prueba unitaria y tiene un icono de prueba de unidad:

Target Membership [X] Foo [ ] FooTests


Si está utilizando Cocoapods, su archivo de archivo solo necesita las dependencias en la sección para el objetivo principal, no los objetivos de prueba. Si agrega dependencias duplicadas para los objetivos de prueba, obtendrá el mensaje de error de OP.

target ''MyProject'' do pod ''Parse'' end target ''MyProjectTests'' do end target ''MyProjectUITests'' do end