2013-03-08 14 views
8

I è necessario per sovrascrivere un metodo utilizzando una categoria. Sono anche consapevole dei pericoli con cui lo faccio (questa è una classe privata all'interno di un'altra classe e nessuno scriverà mai un altro metodo di categoria prevalente, quindi nessun comportamento indefinito è garantito). Ho visto un sacco di simile questions ma tutti indirizzo sopprimendo la avvertimento compilatore utilizzando qualcosa di simile:Come si sopprime l'avviso del linker quando si esegue l'override di un metodo di istanza di classe in una categoria

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" 

// do your override 

#pragma clang diagnostic pop 

Tuttavia questo lascia ancora il avvertimento linker. È possibile sbarazzarsi di esso per il mio particolare override che considero sicuro, in Xcode 4.6?

Ecco un sample GitHub project che illustra il problema.

+0

Se volessi esporti, perché ne hai bisogno, potremmo forse offrirti soluzioni alternative. il tuo codice di esempio non ci mostra il motivo, in quanto non è ovvio in questo esempio, perché non usi la sottoclasse. – vikingosegundo

+0

@vikingosegundo Voglio sostituire un'implementazione del metodo mantenendo comunque l'accesso alla sua superclasse (e trovo questo un approccio più elegante rispetto al metodo swizzling). Vedi questa domanda per maggiori informazioni: http://stackoverflow.com/questions/15291390/in-objective-c-how-do-you-entely-replace-a-method-of-a-parent-class-while-pre In quella domanda ho chiesto soluzioni alternative al problema. Qui sto solo chiedendo come sopprimere gli avvertimenti effettivi del linker per riferimento futuro. – lms

+0

Non considererei mai la soppressione di un avvertimento elegante. Forse è meno brutto del metodo swizzling ... – vikingosegundo

risposta

0

OK, come ho spiegato nel mio commento quello che stai cercando di fare è pericoloso e non dovrebbe essere fatto. Ho anche suggerito di leggere lo runtime documentation per capire perché e conoscere altri metodi per raggiungere il tuo obiettivo. Dovresti leggerlo.

In ogni caso un'alternativa a ciò che si sta facendo, che produce gli stessi esatti risultati senza innalzare così tante bandiere rosse, è di usare l'ambiente di runtime per "saltare" una classe nella gerarchia di inizializzazione, "sovrascrivere" effettivamente metodo della superclasse.

Ecco una possibilità di come è fatto, nel progetto di esempio, modificare l'implementazione della classe FunkyBranch a questo:

#import "FunkyBranch.h" 
#import <objc/runtime.h> 

typedef id(*InitIMP)(id,SEL); 

@implementation FunkyBranch 

-(id) init 
{ 
    InitIMP superSuperInit = (InitIMP)class_getMethodImplementation([[self superclass] superclass], @selector(init)); 

    self = superSuperInit(self, @selector(init)); 
    if (self) 
    { 
     NSLog(@"FunkyBranch initialized"); 
    } 
    return self; 
} 

@end 

avrà gli stessi risultati come l'implementazione corrente senza i pericoli di ciò che state facendo .

Si prega di tenere presente che fondere il puntatore di funzione sul tipo corretto è della massima importanza, inoltre credo ancora che si debba riconsiderare il proprio approccio invece di forzare il runtime a fare qualcosa che non è progettato per fare. In ogni caso, questo risponde alla tua domanda.

+0

FWIW, questo è un modo abbastanza ragionevole (gli OP) per sovrascrivere i metodi, ad esempio per il test. Noi sovrascriviamo i metodi in questo modo per controllare le loro implementazioni, utilizzando categorie caricate solo per un obiettivo di test. Non è così terribile, IMO. Questo è un trucco ben fatto, anche se un po 'offuscato. – tooluser

Problemi correlati