2010-11-18 12 views
5

Ho iniziato a programmare per iPhone circa un mese fa e ho trovato il sito molto utile. Quindi, anche se qualcuno là fuori potrebbe aiutarmi.Invio di dati tra classi in Cocoa Obiettivo C

Penso di capire le basi di come @property e @synthesise funzionano e utilizzano setter e getter, ma ho un problema.

Dire che ho 3 classi: funzioni, Class1 e Class2.

Funzioni è una classe che contiene tutti i dati e Class1 e Class2 legge i dati da esso e scrive nuovi dati (modifica i dati) su di esso. Tuttavia, sia Class1 che Class2 creeranno la propria istanza di funzioni in quanto si tratta fondamentalmente di un progetto per i dati.

Quindi se Class1 scrive o "imposta" alcuni dati (diciamo) 5 su Funzioni e Class2 lo "ottiene", Class2 restituirà 0 come Class1 ha solo scritto 5 alla sua istanza di Funzioni, che Class2 non può vedere .

Suppongo che sia il primo? In secondo luogo, come faccio a farlo in modo che Class1 e Class2 possano vedere gli stessi dati da ottenere e impostare.

Grazie per l'aiuto. Mi rendo conto che questo potrebbe includere un argomento che non ho ancora appreso, ma se così fosse mi piacerebbe sapere di cosa si tratta, quindi posso farlo.

risposta

6

Si dispone di un numero di opzioni che tutte riducono per garantire che Class1 e Class2 utilizzino la stessa istanza dell '"oggetto condiviso".

  1. Esprimere espressamente la stessa istanza in Class1 e Class2 dall'esterno, anziché consentire a Class1 e Class2 di creare un'istanza autonomamente; oppure
  2. Fornire un inizializzatore singleton alla classe Functions, quindi assicurarsi che Class1 e Class2 lo utilizzino; oppure
  3. Utilizzare un modello di progettazione noto come modello di registro e assicurarsi che Class1 e Class2 ottengano la loro istanza della classe di funzioni dal registro; oppure
  4. Utilizzare l'iniezione di dipendenza (complessa).

Scenario (1) è il più semplice da comprendere poiché va esattamente così:

Functions *funcs = [[Functions alloc] init]; 

Class1 *obj1 = [[Class1 alloc] initWithFunctions:funcs]; 
Class2 *obj2 = [[Class2 alloc] initWithFunctions:funcs]; 
/* or alternatively use setters after initialization */ 

Scenario (2) è il seguente semplice ed è molto comune. Il cacao fornisce inizializzatori singleton a molte delle sue classi. Ogni volta che vedi +shared... come prefisso per un inizializzatore, probabilmente restituisce un singleton.

@implementation Functions 

+(id)sharedFunctions { 
    static Functions *sharedFunctions = nil; 

    @synchronized(self) { 
    if (sharedFunctions == nil) { 
     sharedFunctions = [[self alloc] init]; 
    } 

    return sharedFunctions; 
    } 
} 

@end 

La variabile statica viene inizializzata una sola volta, il che significa che è possibile pigramente caricare un'istanza dell'oggetto in esso mediante un controllo per il suo valore iniziale (che si verifica una sola volta). Ogni chiamata successiva al metodo restituisce la stessa istanza.

Functions *f1 = [Functions sharedFunctions]; 
Functions *f2 = [Functions sharedFunctions]; 

/* f1 == f2; */ // always 

Opzione (3) non è visto molto in Objective-C rispetto ad in altre lingue e raggiunge più o meno gli stessi obiettivi come il Singleton. L'idea è che tu abbia un dizionario di oggetti che possono essere cercati per chiave. Tutto ciò che ha bisogno di accedere agli elementi nel registro richiede solo il registro per la propria istanza. In genere il registro stesso sarebbe un singleton.

L'opzione (4), l'iniezione di dipendenza, è in realtà una soluzione molto elegante con una serie di vantaggi a costo di complessità aggiuntiva. I benefici derivano dal fatto che hai assicurato che le dipendenze siano sempre liberamente accoppiate (il che rende lo swapping delle implementazioni, e l'unità testare le dipendenze in modo indipendente molto più semplice). La complessità deriva dai meccanismi non standard per il recupero delle istanze di ciò che è necessario.

L'iniezione di dipendenza ruota intorno all'idea che nessun oggetto istanzia le proprie dipendenze. Invece di fare affidamento su qualcos'altro per fornire quelle dipendenze. Quel "qualcos'altro" è noto come contenitore per l'iniezione di dipendenza. Un contenitore per le dipendenze è effettivamente un livello in cima al modello del registro, poiché il contenitore può contenere istanze predefinite delle dipendenze o saprà come istanziare nuove istanze.

Nel caso più semplice, l'iniezione di dipendenza è esattamente ciò che ho dimostrato nell'opzione (1). Non hai nemmeno bisogno di un contenitore per l'iniezione di dipendenza per raggiungere questo obiettivo.

Spostando verso l'alto un livello di complessità, l'iniezione di dipendenza introduce il concetto di un contenitore DI, che incapsula un numero di schemi di progettazione esistenti (il registro, come mostrato nell'opzione (3), il singleton (probabile, ma non strettamente) e la fabbrica (per sapere come creare nuove istanze di oggetti che gestisce)

La dimostrazione di un'implementazione completa di un contenitore DI verrebbe probabilmente oltre lo scopo di questa domanda, ma da un punto di vista dell'interfaccia pubblica, un'implementazione potrebbe essere simile a questa:

DIContainer *container = [DIContainer sharedContainer]; 

[container registerClass:[ClassA class]]; 
[container registerClass:[ClassB class]]; 
[container registerDependentProperty:@selector(setClassA:) 
         withInstanceOf:[ClassA class] 
          forClass:[ClassB class]]; 

ClassB *obj = [container makeInstanceOfClass:[ClassB class]]; 
NSLog(@"ClassB's -classA type = %@", [[obj classA] class]); 

Ho appena digitato quello in cima alla mia testa in al centro di questo post, quindi non dare per scontato che sia accurato al 100%, ma ottieni il concetto. Il contenitore è stato informato che quando inizializza istanze di ClassB, deve quindi richiamare -setClassA:, utilizzando un'istanza di ClassA, che viene inizializzata anche in base alle regole definite nel contenitore (in questo caso non ci sono dipendenze da ClassA quindi è solo restituisce un'istanza pianura

Se si prende niente di più lontano da questa risposta, basta ricordare le opzioni (1) e (2);.)

+2

Cheers man, questo è davvero utile. Sono andato per l'opzione 2 e funziona bene. Le opzioni 3 e 4 mi sono un po 'un po' in su la testa, ma le rileggerò domani dopo aver dormito un po '. Potrebbe avere più senso al mattino. Grazie per l'aiuto, però, molto utile. :-D – Baza207

+1

Nessun problema, penso che la tua scelta con l'opzione (2) sia buona.L'opzione (1) è "tecnicamente" la migliore in quanto il singleton ha una certa cattiva reputazione tra molti sviluppatori, a causa della difficoltà con cui può essere testato (ambiente di test non pulito). Tuttavia, usato correttamente è perfettamente a posto. In realtà, dato che Objective-C non ha un singolo inizializzatore/costruttore esclusivo come gli altri linguaggi, il singleton non è forzato al 100%, quindi può essere comunque lavorato in testing. L'opzione 3 è abbastanza semplice, ma sì, l'opzione (4) è un argomento che confonde anche gli sviluppatori esperti. – d11wtq

+0

So che questa domanda è vecchia, ma questo mi ha totalmente aiutato. +1 –

0

Questa è davvero una domanda sulla programmazione orientata agli oggetti in generale, ma la soluzione si applica anche a Objective-C. Quello che vuoi fare è creare un'istanza di funzioni. Quell'istanza dovrebbe essere condivisa tra le istanze di Class1 e Class2.

Functions *f = [[Functions alloc] init]; 
Class1 *c1 = [[Class1 alloc] init]; 
Class2 *c2 = [[Class2 alloc] init]; 
// set the value of a instance variable of f to the value of aValue from c1 
[f setSomeValue:[c1 aValue]]; 
// now change it to c2's aValue 
[f setSomeValue:[c2 aValue]]; 
+0

Ok, questo ha senso. Quindi suppongo che inseriresti i bit solo con Class1 nel file Class1 e inserirò solo i bit con Class2 nel file Class2. Anche se init l'istanza di Funzioni va in entrambi? Scusate se sto ripetendo le cose, ma ho continuato a ripetere questa roba e la mia mente è rimasta un po 'turbata. – Baza207

1

È necessario leggere la Guida ai cacao fondamentali. La sezione relativa alla tua domanda è denominata Communicating with Objects.

+0

Cheers per il collegamento. :-) – Baza207

0

ci sono un sacco di riferimenti on-line là fuori, ma ho trovato questo prenotare per essere un grande vantaggio. Programmazione in Objective-C 2.0 (2nd Ed.) Di Stephen G. Kochan. È un ottimo punto di partenza.