2009-05-31 12 views
33

He creado una biblioteca estática para albergar algunos de mis códigos como categorías.El método de llamada en la categoría incluida desde la biblioteca estática del iPhone causa NSInvalidArgumentException

Tengo una categoría para UIViews en "UIView-Extensions.h" llamadas Extensiones.

En esta categoría tienen un método llamado:

- (void)fadeOutWithDelay:(CGFloat)delay duration:(CGFloat)duration; 

llamada a este método funciona bien en el simulador de la configuración de depuración.

Sin embargo, si intenta ejecutar la aplicación en el dispositivo consigo un NSInvalidArgumentException:

[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView fadeOutWithDelay:duration:]: unrecognized selector sent to instance 0x1912b0 

Parece por alguna razón UIView-Extensions.h no se incluye en el dispositivo construye.


Lo que he comprobado/intentado

Traté de incluir otra categoría para NSString, y tenía el mismo problema.

Otros archivos, como clases y funciones completas funcionan bien. Es un problema que solo sucede con las categorías.

Hice todos los objetivos limpios, lo que no solucionó el problema.

Revisé el proyecto de biblioteca estática, las categorías se incluyen en los grupos "copiar encabezados" y "compilar fuentes" del destino.

La biblioteca estática se incluye en el grupo principal de proyectos "enlace binario con biblioteca".

Otro proyecto al que he agregado la biblioteca estática funciona muy bien.

He eliminado y volver a agregar la biblioteca estática sin suerte

bandera enlazador -ObjC se establece

¿Alguna idea?


salida nm

libFJSCodeDebug.a(UIView-Extensions.o): 
000004d4 t -[UIView(Extensions) changeColor:withDelay:duration:] 
00000000 t -[UIView(Extensions) fadeInWithDelay:duration:] 
000000dc t -[UIView(Extensions) fadeOutWithDelay:duration:] 
00000abc t -[UIView(Extensions) firstResponder] 
000006b0 t -[UIView(Extensions) hasSubviewOfClass:] 
00000870 t -[UIView(Extensions) hasSubviewOfClass:thatContainsPoint:] 
000005cc t -[UIView(Extensions) rotate:] 
000002d8 t -[UIView(Extensions) shrinkToSize:withDelay:duration:] 
000001b8 t -[UIView(Extensions) translateToFrame:delay:duration:] 
     U _CGAffineTransformRotate 
000004a8 t _CGPointMake 
     U _CGRectContainsPoint 
     U _NSLog 
     U _OBJC_CLASS_$_UIColor 
     U _OBJC_CLASS_$_UIView 
     U ___CFConstantStringClassReference 
     U ___addsf3vfp 
     U ___divdf3vfp 
     U ___divsf3vfp 
     U ___extendsfdf2vfp 
     U ___muldf3vfp 
     U ___truncdfsf2vfp 
     U _objc_enumerationMutation 
     U _objc_msgSend 
     U _objc_msgSend_stret 
     U dyld_stub_binding_helper 
+0

¿Qué dice específicamente el mensaje de excepción? –

+1

Lo agregué en la pregunta –

+0

encontré interesante esta parte de su pregunta 'las categorías están incluidas en los grupos de" encabezados de copiado "y" fuentes de compilación "del objetivo. .. típicamente las categorías son * no * llamadas por proyectos que contienen el dicha biblioteca estática ... ¿por qué debería incluirse en la sección 'copiar encabezados'? Apple no hace mención de ello en su [tutorial] recientemente publicado (http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf) – abbood

Respuesta

30

La única solución que funcionó fue incluir:

"-all_load"

en otras banderas de engarce.

EDIT: Asegúrese de agregar este marcador al proyecto, incluida la biblioteca estática, no a la biblioteca estática en sí.

Sé que este no es el método correcto, pero está funcionando por ahora.

Quizás sea un problema de OS 3.0 ya que este fue el trabajo para Three20 también.

+0

Marque esta respuesta a otra pregunta: http://stackoverflow.com/questions/2906147/what-does-the-all-load-linker-flag-does/2906210 # 2906210 – Sophistifunk

+7

Solo quería agregar que necesita agregar este indicador al proyecto, incluida la biblioteca estática, no en la biblioteca estática en sí. – Pascal

+0

¡Solo quería GRACIAS! Esto ayudó mucho. – Romain

14

Desafortunadamente, debido a la qué categorías de trabajo y la naturaleza dinámica del tiempo de ejecución de Objective-C, no todo funciona bien con las bibliotecas estáticas. El motivo por el que recibe este error es que la implementación de la categoría en la biblioteca estática nunca está realmente vinculada a la imagen ejecutable porque el compilador no tiene forma de saber que el código de implementación será necesario en tiempo de ejecución.

Para solucionar esto, puede forzar al vinculador a copiar archivos de objeto de un archivo estático para todas y cada una de las categorías de clase y categoría de Objective-C. La desventaja es que el ejecutable incluirá un código de imagen para las clases que posiblemente no esté utilizando. Para que el enlazador incluya el código de categoría, agregue -ObjC a la configuración de compilación OTHER_LD_FLAGS en Xcode.La implementación de su categoría ahora se copiará del archivo estático a su ejecutable y no obtendrá la excepción de tiempo de ejecución.

+0

que ya tenía el indicador del enlazador -ObjC establecido. –

+0

Bueno, ese es el problema. ¿Intentó ejecutar nm en el archivo para asegurarse de que el código del objeto esté realmente en el archivo? –

+0

Corey - ¿se aseguró de que el indicador del enlazador -ObjC esté configurado en * todas * configuraciones y no solo en la configuración de depuración? –

0

En el pasado, pude forzar el enlace de la categoría con -u .objc_category_name_UIView_Extensions, pero con el entorno de desarrollo 3.0 que está roto y la única opción parece ser -all_load.

2

Me encontré con este problema recientemente. No pude hacer funcionar la opción -all_load, cuando noté que otra categoría tenía el trabajo de DID. Era flojo para esta categoría y lo incluí en otro archivo.

Finalmente creé una clase ficticia (sin métodos, variables de instancia) e incluí la implementación de mis categorías en el archivo .m para esa clase ficticia. Después de hacer esto, mis categorías comenzaron a funcionar incluso después de eliminar el indicador -all_load.

Esto fue en iPhone OS 3.1.3.

Esto ciertamente no es la forma correcta de solucionarlo, pero parecía funcionar.

El código de muestra completo está en mi blog para mis categorías (triviales).

0

Tuve el mismo problema con las categorías en mi biblioteca estática. En mi caso, "-all_load" no ayudó, ya que causó una gran cantidad de errores de compilación (mi biblioteca estática es un envoltorio alrededor de otra lib privada de C/C++).

Lo resolví mediante un truco sugerido en http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html que simplemente implicaba agregar una definición de clase ficticia (vacía) a los archivos de categorías. Usando este truco, guardé "-ObjC" pero dejé caer "-all_load" en la configuración del enlazador de la aplicación y funcionó bien en el dispositivo.

6

Acabo de hablar con un ingeniero de Apple sobre esto, y esto se ha tratado en ld con versiones> 100. Esto está incluido en XCode4. Me guió a través de esto y lo intenté yo mismo y, de hecho, el problema de categoría es fijo.

Elimine "-all_load" y regrese a "-ObjC" en la configuración de compilación con el nuevo enlazador.

+0

gracias Lo intentaré –

+0

Lamentablemente, esto todavía no funciona en Xcode4. Puede solucionarlo haciendo una clase vacía en su archivo de categoría, que funciona para todo excepto para pruebas unitarias. Ni siquiera -toda_carga puede hacer que las pruebas unitarias encuentren su código de categoría a menos que asocie el archivo con su objetivo de prueba. – Karl

+1

De hecho, se volvió a romper en Xcode 4. He aprendido de la bandera -force_load en su lugar, lo que hace el truco. – ev0

5

Si usa Xcode 3.2, puede evitar el uso de -all_load y en su lugar usar -force_load solo para la biblioteca en cuestión, lo que debería ser un poco más eficiente.

Esto se describe en un control de calidad técnico de Apple recientemente actualizada: http://developer.apple.com/mac/library/qa/qa2006/qa1490.html

3

La cuestión que se necesitaban -all_load o -force_load banderas enlazador para enlazar categorías ha sido fixed in LLVM. El arreglo se envía como parte de LLVM 2.9. La primera versión de Xcode que contiene el arreglo es el envío de Xcode 4.2 con LLVM 3.0.Las correcciones mencionadas ya no son necesarias cuando se trabaja con Xcode 4.2. La bandera -ObjC sigue siendo necesaria al vincular los binarios ObjC

+0

Estoy usando LLVM 3.0 con XCode 4.2.1 y todavía tengo el problema de que las categorías en las bibliotecas estáticas no funcionan. – Rick

+0

¿Pero está usando la bandera del enlazador '-ObjC'? Esto es y seguirá siendo necesario. Solo el indicador '-all_load' ya no es necesario. – tonklon

+0

sí compilando con la marca -ObjC funciona. Después de crear una categoría de prueba simple, la compilación funcionó. Debe haber sido algo raro en el archivo de proyecto anterior, después de agregar todo el código a un nuevo proyecto todo funciona bien. – Rick

2

Acabo de tener el mismo problema, pero no funcionó agregar cualquier combinación de las marcas descritas (-ObjC, -all_load, -force_load).

Resultó que no había marcado la casilla "Agregar a destino" al agregar los archivos al proyecto. Quité los archivos del proyecto y los agregué nuevamente, esta vez asegurándome de que esa casilla esté marcada. Esto solucionó el problema.

Cuestiones relacionadas