2012-12-10 12 views
5

ho una classe di test all'interno del mio progetto che è lì durante la fase di sviluppo, ma sarà compilato per la costruzione App Store.Non capisco come NSClassFromString può essere utilizzato per chiamate condizionale

ho letto in diversi libri che NSClassFromString può essere utilizzato per determinare se una classe esiste con codice di esempio come:

if (NSClassFromString(@"SomeClass") != nil) 
{ 
[SomeClass someMethod]; 
} 
else 
{ 
code not using SomeClass 
} 

Tuttavia dopo aver messo in pratica nel mio progetto, trovo che ho' Sto ottenendo un errore di collegamento per il target in cui ho rimosso il file sorgente contenente SomeClass.

Quindi la mia conclusione è che questo meccanismo per determinare la presenza/assenza di una classe è utile solo se tale classe si trova all'interno di una libreria o di un file sorgente in cui si utilizzano altre classi (un dettaglio che manca nei libri che menzionano questo tecnica). O mi manca qualcosa?

risposta

6

NSClassFromString ricerche il runtime per la classe di nome. Pertanto, determinerà se la classe esiste.

per il compilatore con successo per ottenere riferimenti statici ultimi come [SomeClass someMethod] ha bisogno di qualcosa di linkare.

Hai ragione che il meccanismo funziona quindi quando ti colleghi a qualcosa come Foundation e Apple aggiunge una classe extra lì, come verificare se esiste lo NSJSONSerialization.

Funziona anche se debole contro una struttura che può o non può essere presente. Quindi ad es. potresti indebolire il collegamento con Twitter.framework e utilizzare [TWRequest alloc] .... Sarai comunque in grado di creare e implementare su iOS 4 dove non esiste affatto un framework di Twitter.

Apple ha leggermente modificato il modo in cui le librerie sono memorizzate e sono in fase di transizione per consentire if([TWRequest class]) o qualsiasi altra cosa da utilizzare al posto dello NSClassFromString esplicito in cui il collegamento è debole.

Tuttavia nel tuo caso suona come si desidera o link per una libreria statica o no un link ad esso? Quindi la classe potrebbe o potrebbe non essere disponibile in fase di esecuzione ma potrebbe anche non essere visibile al linker?

In tal caso solo bisogno di evitare riferimenti letterali alla metaclasse. Così si potrebbe fare qualcosa di simile:

Class someClassMetaClass = NSClassFromString(@"SomeClass"); 

if(someClassMetaClass) 
{ 
    SomeClass *instance = [[someClassMetaClass alloc] init]; 
    /* ... */ 
} 

Finché il file di intestazione è visibile il compilatore sarà felice che consente di specificare il tipo di SomeClass per i puntatori (perché che non va nel binario comunque) e la volontà essere in grado di suggerire i consueti autocompletamenti e avvertimenti sull'interfaccia pubblicata. Assicurati di indirizzare sempre il metaclass attraverso un puntatore allo Class che hai ottenuto dal runtime piuttosto che direttamente. In questo modo non c'è niente che il linker debba seguire.

+0

Grazie. Sto costruendo una libreria con varianti "complete" e "leggere" con alcune classi mancanti nella versione lite. Con poche altre classi il comportamento dipende da se sono presenti o meno. – Gruntcakes

Problemi correlati