Domanda

Come posso creare un metodo nel @implementation di una classe senza definire nel @interface?

Per esempio, ho un costruttore che fa un po 'di inizializzazione e quindi legge i dati da un file. Voglio scomporre il codice del file di lettura in un metodo separato che ho poi chiamo dal all'interno del costruttore. Io non voglio definire questo metodo nell'intestazione perché è privato solo per questo contesto @implementation.

È possibile?

Ecco il mio esempio. Ho un piccolo programma che legge un Todo task-list da un file.

Ecco l'@interface:

@interface TDTaskList : NSObject {
  NSString* name; // The name of this list.
  NSMutableArray* tasks;  // The set of tasks in this list.
}

-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;

@end

E qui fa parte del @implementation:

-(id)initListOfName:(NSString*)aName {
  if (self = [super init]) {
    name = aName;

    NSArray* aTasks = [self loadListWithName:aName];
    tasks = [NSMutableArray arrayWithArray:aTasks];
  }

  return self;
}

-(NSArray*)loadListWithName:(NSString*)aName {
  // TODO This is a STUB till i figure out how to read/write from a file ...

  TDTask* task1 = [[TDTask alloc] initWithLabel:@"Get the Milk."];
  TDTask* task2 = [[TDTask alloc] initWithLabel:@"Do some homework."];

  return [NSArray arrayWithObjects:task1, task2, nil];
}

Quello che voglio fare è quello di non necessario definire quanto segue nell'interfaccia:

-(NSArray*)loadListWithName:(NSString*)aName;
È stato utile?

Soluzione

Se si inserisce la realizzazione di un metodo prima di qualsiasi codice che chiama non è necessario definirlo nell'intestazione.

Quindi in questo caso mettere loadListWithName: di fronte a initListOfName:. nel blocco @implementation e sarà un bene

Nota: Solo perché non è definita nell'intestazione non significa che il metodo non può essere chiamato dal codice al di fuori dell'oggetto. Objective-C non ha metodi privati.

Altri suggerimenti

Come Andy accennato nei commenti, è possibile utilizzare estensioni (che assomigliano a una categoria senza nome). La differenza è che deve implementare i metodi dichiarati in un'estensione, mentre il compilatore non verifica che si sceglie di implementare metodi dichiarati in una categoria.

.h:

@interface MyObject : NSObject
{
    NSNumber *number;
}
- (NSNumber *)number;
@end

.m:

@interface MyObject ()
- (void)setNumber:(NSNumber *)newNumber;
@end

@implementation MyObject

- (NSNumber *)number
{
    return number;
}
- (void)setNumber:(NSNumber *)newNumber
{
    number = newNumber;
}
@end

Si potrebbe utilizzare categorie :

// In TDTaskList.m
@interface TDTaskList(TDTaskListPrivate)
-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;
@end

@implementation TDTaskList(TDTaskListPrivate)

// implementation of initListOfName and loadListWithName ...

@end

Hai due opzioni ragionevoli. Entrambi sono stati sostanzialmente descritto già, ma secondo me erano un po 'poco chiaro o anche semplicemente sbagliato.

Le categorie non sono uno di loro in quanto sono pensati per quanto ne so il completamente diverso scopo di rompere le implementazioni in più file di origine.

  • Fare come Nathan sopra descritto. Anche se è sbagliato con la sua ultima ipotesi (metodi privati).
  • Utilizzare una definizione di metodo di estensione privata per consentire avanti riferimento come segue:

    1. rimuovere la definizione del loadListWithName dal colpo di testa del tutto
    2. aggiungere il seguente nella fonte (.m) prima del blocco @implementation
    @interface TDTaskList (PrivateMethods)
    -(NSArray*)loadListWithName:(NSString*)aName;
    @end
    
    @implementation ...
    

  • Autorizzato sotto: CC-BY-SA insieme a attribuzione
    Non affiliato a StackOverflow
    scroll top