2011-08-31 9 views
11

Ho un protocollo denominato MyProtocol. MyProtocol ha un metodo richiesto:Rendere classe conforme al protocollo con categoria per metodi esistenti

- (NSUInteger)length; 

E alcuni altri metodi.

Ora voglio rendere la classe NSString conforme a MyProtocol con una categoria. In questo modo:

@interface NSString (NSStringWithMyProtocol) <MyProtocol> 
@end 

In questa categoria a implementare tutti i metodi escludendo il metodo 'lunghezza', perché voglio l'implementazione NSString originale. Non voglio sovrascriverlo in questa particolare classe.

Ora ricevo un avviso a causa di un'implementazione incompleta di MyProtocol nella categoria.

So che ci sono alcune soluzioni per risolvere questo.

  1. rendere il metodo opzionale
  2. Pointer Swizzling
  3. Aggiunta sottoclasse di classe che è conforme al protocollo. Quindi tralascia l'implementazione.

Non voglio usare queste opzioni perché provocano un cattivo design per il resto del mio codice.
L'opzione 3 non è buona, poiché le sottoclassi dirette esistenti non saranno conformi al protocollo.

Qualcuno sa come rimuovere l'avviso senza implementare il metodo di lunghezza?

NOTA: Classe, categoria e protocollo sono solo esempi. Ho incontrato questo problema con altre classi che non potevo pubblicare. Grazie

MODIFICA: Aggiunta la terza opzione.

codice completo:

Il protocollo:

@protocol MyProtocol <NSObject> 

- (void) myMethod; 
- (NSInteger) length; 

@end 

La categoria intestazione:

#import <Foundation/Foundation.h> 
#import "MyProtocol.h" 

@interface NSString (MyProtocol) <MyProtocol> 
@end 

L'implementazione categoria:

@implementation NSString (MyProtocol) 

- (void)myMethod { 

} 

@end 

Ciò comporta i seguenti avvertimenti.

Incomplete implementation 

Method in protocol not implemented 

In questa immagine potete vedere il mio avvertimento: Screen shot

ho provato la compilazione con LLVM GCC 4.2 e il 3.0 del compilatore LLVM di Apple. Ho anche compilato xcode 4.0.2 e Xcode 4.2. Sono su OS X 10.6.8.

risposta

7

Non riesco a riprodurre questo problema. Puoi pubblicare il codice che lo dimostra? Il seguente compila senza avvisi su 10.7.

#import <Foundation/Foundation.h> 

@protocol MyProtocol <NSObject> 
- (NSUInteger)length; 
@end 

@interface NSString (NSStringWithMyProtocol) <MyProtocol> 
@end 

int main (int argc, const char * argv[]) { 
    @autoreleasepool { 
    id<MyProtocol> foo = @"foo"; 
    NSLog(@"%@", foo);  
    } 
    return 0; 
} 
+1

Ho aggiunto il mio codice. Vedo anche che cosa è diverso. Non hai definito un'implementazione per la categoria. –

+1

Clang a quanto pare è molto più severo su questo di gcc. Nella stragrande maggioranza dei casi, questa è una buona cosa, ma in questo caso credo che tu abbia spinto al limite dell'attuale implementazione. Vorrei aprire un difetto contro il clang. –

+1

Penso che firmerò come risposta corretta. Si noti che funzionerà solo quando una classe ha già implementato tutti i metodi definiti nel protocollo. L'implementazione delle categorie non può esistere con un'implementazione parziale del protocollo. –

0

Si potrebbe considerare questo un po 'di un hack, e non so se sarà anche il lavoro, ma come circa dichiarandolo come una proprietà di sola lettura

@property (readonly, assign) NSUInteger length; 

e poi nella realizzazione del vostro categoria, make it @dynamic

+1

Potrebbe funzionare per un getter, ma non per il setter. Non ha indicato che questo era solo un esempio. Non ero in grado di parlare del mio codice di produzione. –

+0

@Mats: crea una proprietà di lettura/scrittura, quindi – JeremyP

+1

True. Ma questo non solo risolverà i metodi setter/getter. Come notato nel mio precedente commento, mi occupo di altre classi e metodi. –