2009-05-31 7 views
33

Ho creato una libreria statica per ospitare alcune delle mie categorie di codice.Il metodo di chiamata sulla categoria inclusa nella libreria statica di iPhone causa NSInvalidArgumentException

Ho una categoria per le visualizzazioni di UIView in "UIView-Extensions.h" con estensione.

In questa categoria ho un metodo chiamato:

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

si chiama questo metodo funziona bene sul simulatore in configurazione di debug.

Tuttavia, se tenta di eseguire l'applicazione sul dispositivo ottengo 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 

Sembra per qualche ragione UIView-Extensions.h non viene incluso nel dispositivo costruisce.


Quello che ho controllato/provato

ho cercato di includere un'altra categoria per NSString, e ha avuto lo stesso problema.

Altri file, come intere classi e funzioni funzionano bene. È un problema che solo accade con le categorie.

Ho fatto un pulito tutti i target, che non ha risolto il problema.

Ho controllato il progetto della libreria statica, le categorie sono incluse nei gruppi "headers" e "compilare sources" del target.

La libreria statica è inclusa nel progetto principale "link binary with library" group.

Un altro progetto che ho aggiunto alla libreria statica funziona perfettamente.

ho cancellato e ri-aggiunta la libreria statica senza fortuna

-ObjC bandiera del linker è impostato

Tutte le idee?


uscita 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

Che cosa dice, in particolare, il messaggio di eccezione? –

+1

L'ho aggiunto alla domanda –

+0

ho trovato interessante questa parte della tua domanda 'le categorie sono incluse nei gruppi" headers "e" compilation sources "del target. .. tipicamente le categorie sono * non * chiamate da progetti contenenti il ha detto la libreria statica .. perché dovrebbe essere inclusa nella sezione 'copia intestazioni? Apple non ne fa menzione nel suo [tutorial] pubblicato di recente (http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf) – abbood

risposta

30

L'unica soluzione che ha funzionato è stato quello di includere:

"-all_load"

in altre bandiere linker.

MODIFICA: Assicurarsi di aggiungere questo flag al progetto, inclusa la libreria statica, non alla libreria statica stessa.

So che questo non è il metodo corretto, ma funziona per ora.

Forse un problema di OS 3.0 poiché questo era il lavoro intorno a Three20 pure.

+0

Controlla questa risposta ad un'altra domanda: http://stackoverflow.com/questions/2906147/what-does-the-all-load-linker-flag-does/2906210 # 2906210 – Sophistifunk

+7

Volevo solo aggiungere che è necessario aggiungere questo flag al progetto, inclusa la libreria statica, non nella stessa libreria statica. – Pascal

+0

Volevo solo GRAZIE! Questo ha aiutato molto. – Romain

14

Purtroppo, a causa del quale le categorie di lavoro e la natura dinamica del runtime Objective-C, non tutto funziona bene con le librerie statiche. Il motivo per cui si ottiene questo errore è che l'implementazione della categoria nella libreria statica non è mai effettivamente collegata all'immagine eseguibile perché il compilatore non ha modo di sapere che il codice di implementazione sarà necessario in fase di esecuzione.

Per ovviare a questo problema, è possibile forzare il linker a copiare i file oggetto da un archivio statico per tutte le immagini di Classe e Categoria Objective-C. Lo svantaggio è che il tuo eseguibile includerà il codice immagine per le classi che potresti non utilizzare affatto. Per fare in modo che il linker includa il codice di categoria, aggiungi -ObjC all'impostazione di build OTHER_LD_FLAGS in Xcode.L'implementazione della categoria verrà ora copiata dall'archivio statico al file eseguibile e non si otterrà l'eccezione di runtime.

+0

Ho già avuto il flag flag -ObjC impostato. –

+0

Bene, questo è il problema. Hai provato a eseguire nm sull'archivio per assicurarti che il codice oggetto lo stia effettivamente trasformando nell'archivio? –

+0

Corey: ti sei assicurato che il flag link -ObjC sia impostato in * tutte * le configurazioni e non solo nella configurazione di Debug? –

0

In passato ero in grado di forzare il collegamento della categoria con -u .objc_category_name_UIView_Extensions, ma con l'ambiente di dev 3.0 che è rotto e l'unica opzione sembra essere -all_load.

2

Mi sono imbattuto recentemente in questo problema. Non ero in grado di far funzionare -all_load, quando ho notato che un'altra categoria aveva il lavoro DID. Ero pigro per questa categoria e l'ho incluso in un altro file.

Alla fine ho creato una classe dummy (senza metodi, variabili di istanza) e incluso l'implementazione delle mie categorie nel file .m per quella classe dummy. Dopo averlo fatto, le mie categorie hanno iniziato a funzionare anche dopo aver rimosso il flag -all_load.

Questo era su iPhone OS 3.1.3.

Questo sicuramente non è il modo giusto per risolverlo, ma sembrava funzionare.

Il codice di esempio completo è sul mio blog per le mie categorie (banali).

0

Ho avuto lo stesso problema con Categorie nella mia libreria statica. Nel mio caso, "-all_load" non ha aiutato in quanto ha causato un sacco di errori di compilazione (la mia libreria statica è un wrapper attorno ad un'altra lib C/C++ privata).

Ho risolto il problema con un suggerimento suggerito a http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html che comportava semplicemente l'aggiunta di una definizione di classe fittizia (vuota) ai file di categoria. Usando questo trucco, ho mantenuto "-ObjC" ma ho abbandonato "-all_load" nelle impostazioni del linker dell'applicazione e ha funzionato correttamente sul dispositivo.

6

Ho appena parlato con un ingegnere Apple su questo, e questo è stato risolto in ld con le versioni> 100. Questo è incluso in XCode4. Mi ha guidato attraverso questo e l'ho provato io stesso e infatti il ​​problema di categoria è stato risolto.

Estrarre "-all_load" e tornare a "-ObjC" nelle impostazioni di generazione con il nuovo linker.

+0

grazie Lo proverò –

+0

Sfortunatamente, questo non funziona ancora in Xcode4. Puoi aggirare il problema creando una classe vuota nel tuo file di categoria, che funziona per tutto tranne i test unitari. Neanche -all_load può fare in modo che i test di unità trovino il codice di categoria a meno che non si associ il file al target di test. – Karl

+1

Infatti, è stato interrotto nuovamente in Xcode 4. Ho appreso invece il flag -force_load, che fa il trucco. – ev0

5

Se si utilizza Xcode 3.2, è possibile evitare l'utilizzo di -all_load e utilizzare invece -force_load per la sola libreria in questione, che dovrebbe essere leggermente più efficiente.

Questo è descritto in un recente aggiornamento di Apple QA tecnica: http://developer.apple.com/mac/library/qa/qa2006/qa1490.html

3

Il problema che sono stati necessari -all_load o -force_load bandiere linker di collegare le categorie è stato fixed in LLVM. La correzione viene spedita come parte di LLVM 2.9 La prima versione di Xcode che contiene la correzione è Xcode 4.2 in commercio con LLVM 3.0.Le correzioni menzionate non sono più necessarie quando si lavora con Xcode 4.2. La bandiera -ObjC è ancora necessaria quando si collegano i binari objc

+0

Sto usando LLVM 3.0 con XCode 4.2.1 e ho ancora il problema che le categorie nelle librerie statiche non funzionano. – Rick

+0

Ma stai usando il flag linker '-ObjC'? Questo è e rimarrà obbligatorio. Solo il flag '-all_load' non è più necessario. – tonklon

+0

sì la compilazione con il flag -ObjC funziona. Dopo aver creato una semplice categoria di test, la compilazione ha funzionato. Deve essere stato qualcosa di strano nel vecchio file di progetto, dopo aver aggiunto tutto il codice a un nuovo progetto tutto funziona perfettamente. – Rick

2

Ho appena avuto questo stesso problema, ma l'aggiunta di una qualsiasi combinazione delle bandiere descritte (-ObjC, -all_load, -force_load) non ha funzionato.

Si è scoperto che non avevo selezionato la casella "Aggiungi a destinazione" quando si aggiungono i file al progetto. Ho rimosso i file dal progetto e li ho aggiunti di nuovo, questa volta assicurandomi che quella casella fosse selezionata. Questo ha risolto il problema.