Cocoa tutorial – NSTextField, NSButton
In questo tutorial mostrerò come creare una semplice applicazione che prende del testo in ingresso e lo visualizza nella label di una finestra.
Le fasi principali consistono nel creare il progetto, disegnare l’interfaccia, collegare l’interfaccia al codice e implementare le azioni tra utente e interfaccia.
Faremo uso di XCode, Objective-C e Cocoa. Quel che vi serve è avere XCode installato, un po’ di pazienza e voglia di imparare. Se non avete ancora XCode, potete scaricarlo gratuitamente (previa registrazione) da https://developer.apple.com/technology/xcode.html.
Per prima cosa lanciate XCode e dal menu File scegliete “New Project”. Selezionate come tipo di applicazione “Cocoa application”, premete “Choose…”, date un nome al progetto (in questo tutorial useremo il nome “Prova”) e cliccate “Finish”.
Avete appena creato un nuovo progetto funzionante. Se premete su “Build and Go” nella barra degli strumenti, XCode compilerà e lancerà la vostra nuova applicazione, e vedrete una finestrina grigia vuota apparire sullo schermo. Chiudetela (cmd + Q) e tornate all’ambiente di sviluppo.
Dal menu File scegliete “New File”. Nella colonna di sinistra selezionate “Cocoa” e nel riquadro a destra selezionate come tipo di file “Objective-C class”, come in figura; chiamate questo file “ProvaController.m”.
Successivamente premete Next e assicuratevi che sia spuntata la voce “Also create ProvaController.h” e premete Finish.
Abbiamo così appena creato una nuova classe, ProvaController, che utilizzeremo per gestire gli eventi dell’interfaccia grafica e per interagire con essa. La scelta del nome “ProvaController” è convenzionale, e serve ad indicare che ProvaController è la classe dedicata alla gestione degli eventi della nostra interfaccia grafica.
In XCode vedete che sulla sinistra della finestra principale è presente un albero contenente delle cartelle. Trasciniamo i due files appena creati nella cartella “Classes”, in modo da tenere ordinato il progetto.
Analizziamo brevemente le altre cartelle: in “Other Sources” troviamo main.m (che non andremo a modificare) e gli altri files creati di default da XCode, in “Resources” i file dell’interfaccia e le stringhe dell’applicazione (numero versione, nome dell’applicazione, etc.. e le traduzioni), in “Frameworks” i Frameworks utilizzati dal progetto e infine in “Products” la nostra applicazione finita.
Passiamo ora a disegnare l’interfaccia. Per far ciò sarà sufficiente fare doppio clic su “MainMenu.xib” presente in “Resources” e procedere a posizionare gli elementi nella nostra finestra.
Facendo doppio clic su “MainMenu.xib”, vi si aprirà Interface Builder, ovvero il tool di Apple dedicato al disegno e alla progettazione di una qualsiasi interfaccia grafica. Ecco come dovrebbe apparire Interface Builder ad un primo lancio:
Quello che andremo a fare sarà disegnare l’interfaccia, ovvero posizionare nella finestra grigia i controlli che desideriamo, come meglio crediamo.
Nella finestrina “Library” troverete tutti i controlli di cui avrete bisogno. Sarà sufficiente trascinarli, posizionarli e ridimensionarli. Una volta posizionati, non dovrete far altro se non implementare del codice che renda questi controlli funzionanti.
I controlli di cui avremo bisogno in questo tutorial saranno: una Label (NSTextField), una Wrapping Label (NSTextField), una Box (NSBox) e due Button (NSButton). Per trovarli all’interno della libreria digitate il nome nel filtro in basso e trascinate il controllo desiderato sulla finestra, in modo da poterlo posizionare a piacimento.
Il risultato finale sarà il seguente:
Adesso inizia una prima fase di scrittura del codice.
Torniamo a XCode ed editiamo il file ProvaController.h in modo che abbia il seguente contenuto:
// ProvaController.h #import <Cocoa/Cocoa.h> @interface ProvaController : NSObject { //IBOutlets (the inteface's controllers) IBOutlet NSTextField *inputText; IBOutlet NSTextField *displayedText; IBOutlet NSButton *updateButton; IBOutlet NSButton *clearButton; } /* IBActions (the user interface interactions) */ //Updates the text in the Wrapping Label - (IBAction)updateText:(id)sender; //Clears the text in the Wrapping Label and in the TextField - (IBAction)clearText:(id)sender; @end
Praticamente abbiamo definito due NSTextField e due NSButton, che rappresenteranno per noi il ponte tra interfaccia e codice. I metodi updateText: e clearText: servono rispettivamente per aggiornare ed eliminare il contenuto della Wrapping Label (ovvero di displayedText).
Procediamo ora a collegare gli oggetti appena dichiarati, con i controlli dell’interfaccia che abbiamo precedentemente disegnato. In pratica, diremo a XCode quali controlli sono istanziati da quali oggetti dichiarati in ProvaController, e quali metodi chiamare quando l’utente interagisce con i controlli.
In Interface Builder, dalla finestra Library trascinate il controllo “Object” (un cubo blu) nella finestra nominata “MainMenu.xib (English)”. Successivamente, selezionate il nuovo oggetto e, dalla finestrina dell’Inspector, cliccate sul tab “Identity” e selezionate come nome classe “ProvaController”, come in figura:
Ora dobbiamo semplicemente collegare i controlli della finestra con le variabili che abbiamo dichiarato in “ProvaController.h”. Per farlo, selezioniamo l’oggetto appena creato in Interface Builder (come nella figura sopra) e, tenendo premuto il tasto CTRL, colleghiamo Prova Controller con uno dei nostri controlli. Associamo il pulsante “Clear” con “clearButton”, il pulsante “Update” con “updateButton”, il campo di testo con “inputText” e la label multi riga (di cui non vedete il contenuto ma sapete che esiste) con “displayedText”.
Ora facciamo lo stesso per quanto riguarda le interazioni, ovvero colleghiamo i pulsanti all’interfaccia oggetto. Tenendo premuto CTRL, colleghiamo il pulsante “Clear” a “Prova Controller” tramite il metodo “clearText:” e il pulsante “Update” tramite il metodo “updateText:”.
Come intuibile, questi ultimi due passaggi sono più facili a farsi che a dirsi.
Terminata la parte di “disegno” e “collegamento” dell’interfaccia, possiamo passare al codice vero e proprio. Torniamo quindi in XCode (possiamo chiudere tranquillamente Interface Builder).
Il nostro obiettivo è fare in modo che l’utente inserisca una stringa in inputText e che, premendo Update aggiorni displayedText, premendo Clear ne elimini il contenuto. Niente di più semplice!
Andiamo a modificare il file “ProvaController.m”, che contiene appunto l’implementazione dell’header, in cui sono dichiarati i prototipi e le variabili d’istanza.
Aggiorniamone il contenuto come segue:
// ProvaController.m #import "ProvaController.h" @implementation ProvaController - (IBAction)updateText:(id)sender { //Sets displayedText value to inputText value [displayedText setStringValue:[inputText stringValue]]; } - (IBAction)clearText:(id)sender { //Sets displayedText value to a nil string [displayedText setStringValue:@""]; } @end
La nostra applicazione è così terminata. Come avete visto, con pochissime righe di codice abbiamo implementato l’interazione tra utente e applicazione e abbiamo gestito l’invio di messaggi dall’interfaccia al nostro codice.
Ora, un’ultima considerazione: ogni volta che premete “Build and Go”, XCode compila per voi l’applicazione utilizzando una configurazione particolare. Solitamente, durante lo sviluppo e il debugging, si utilizza la configurazione di Debug. Quando dovete però distribuire il vostro prodotto, dovrete averlo compilato in modalità Release. Per far questo in XCode, nella barra degli strumenti, dal menù a tendina denominato “Active Build Configuration”, selezionate Release e premete “Build”. Ora, se andate nella cartella del progetto e cercate la sottocartella “build/Release”, vi troverete dentro il file “Prova.app”, che è appunto il vostro programmato finito.
Seppur semplice, questo tutorial mira a mostrare ai neofiti uno schema sequenziale di come procedere nella realizzazione di un’applicazione in XCode utilizzando il framework Cocoa.
Il materiale presente in questa pagina è frutto del mio ingegno, ma siete liberissimi di distribuirlo. Se avete bisogno di chiarimenti o se volete suggerirmi correzioni o miglioramenti, sentitevi libero di farlo
Cliccate sull’icona per scaricare il progetto del tutorial, creato con l’ultima versione di XCode disponibile (3.1.2):
In this tutorial I’ll show you how to create a Cocoa application that takes a text field value and puts it in a label.
The main steps are the creation of the project, designing the interface, linking the interface to the code and implementing the interactions between the user and the interface.
We’ll use XCode (you can download it at https://developer.apple.com/technology/xcode.html), Objective-C and Cocoa. What you need is XCode installed on your machine and a little bit of patience.
First, launch XCode and select “New Project” from the “File” menu. Select “Cocoa Application”, press “Choose…”, insert the project name (in this tutorial we’ll use the name “Prova”) and click “Finish”.

Creation of a new Cocoa project.
You have just created a new project, and if you press “Build and Go” in the main toolbar, XCode will compile and link the project, and you’ll se your new Cocoa application running. Close it (cmq+Q) and return to XCode.
From “File” menu select “New File” (or press cmd+N) and from the new window select “Cocoa” in the left column and “Objective-C calss” in the main scroll view, as shown in the next figure. Call your new class “ProvaController.m”.

Creating a new file.
Than, press “Next” and check “Also create ProvaController.h” and press “Finish”.

Creating a new file.
We have now created the class ProvaController, and we’ll use it to interact with the XIB file (our graphical user interface). Note that the term “Controller” is conventional, and help the programmers to identify which class does what.
On the left of XCode main window there’s “Groups & Files” tree. Drag and drop “ProvaController.m” and “ProvaController.h” in the “Classes” directory.
Let’s briefly analyze the other directories: in “Other source” there’s “main.m” and other files created automatically by XCode, in “Resources” there are the XIB file and the application’s strings (version number, application’s name, localization strings, etc…), in “Frameworks” there are the Frameworks and the library used by our application and in “Products” there’s our final application.

"Groups and Files" tree.
The next step is designing the interface. To do so, first double click on “MainMenu.xib” and XCode will launch Interface Builder, the tool you’ll use to design interfaces and to comunicate between your classes and the interface.

Interface Builder.
In the “Library” window you’ll find all the controls you need. All you have to do is drag and drop them to the main window, and then resize or positioning them.
The controls we need are: a Label (NSTextField), a Wrapping Label (NSTextField), a Box (NSBox) and two Buttons (NSButton). To find these controls, type their names into the Library’s search box or browse the Library’s tree.
The final result:

Interface preview.
The next step is implementing the code.
Return to XCode and edit ProvaController.h. It must have the follow content:
// ProvaController.h #import <Cocoa/Cocoa.h> @interface ProvaController : NSObject { //IBOutlets (the inteface's controllers) IBOutlet NSTextField *inputText; IBOutlet NSTextField *displayedText; IBOutlet NSButton *updateButton; IBOutlet NSButton *clearButton; } /* IBActions (the user interface interactions) */ //Updates the text in the Wrapping Label - (IBAction)updateText:(id)sender; //Clears the text in the Wrapping Label and in the TextField - (IBAction)clearText:(id)sender; @end
We have defined two NSTextField and two NSButton. They represents our outlets to the interface. updateText: and clearText: are two methods; the first updates the text and the second clears it.
Proceed now to link inputText, displayedText, updateButton and clearButton to the controls that we have previously positioned in the interface; we’ll tell XCode what controls are the instance of what objects, and wich methods to call when user interacts with the interface.
In Interface Builder, drag and drop the control “Object” (a blue cube) in the “MainMen.xib (English)” window. Next, select it, click on tab “Identity” in the “Inspector” window and select as its class name “ProvaController”, as shown in figure:

Linking the interface to ProvaController class.
Now we must simply link our controllers to the objects declared in “ProvaController.h”. To do so, select “Prova Controller” and, holding CTRL, drag your mouse from “Prova Controller” to one of the controls: link the “Clear” button to the “clearButton” object, the “Update” button to the “inputText” object, the textfield to the “inputText” object and the Wrapping Label to the “displayedText” object.
Now, let’s do the same with the methods. Holding CTRL, link the “Clear” button to the “cleatText:” method and the “Update” button to the “updateText:” method.
There’s no more to do in Interface Builder, so close it and return to XCode.
Finally, we must implement the methods declared in “ProvaController.h”. To do so, open “ProvaController.m” and update its content as follows:
// ProvaController.m #import "ProvaController.h" @implementation ProvaController - (IBAction)updateText:(id)sender { //Sets displayedText value to inputText value [displayedText setStringValue:[inputText stringValue]]; } - (IBAction)clearText:(id)sender { //Sets displayedText value to a nil string [displayedText setStringValue:@""]; } @end
Our application is now terminated. As you’ve seen, we’ve implemented the user interaction and the messagges between the interface and the code with few lines.
A note for the most: each time you press “Build and Go”, XCode compiles your project using a particular configuration. When you’re debugging and developing your application, you must use the Debug configuration, but when you decide to deploy it, you must select Release configuration. To do so, select “Release” from the “Active Build Configuration” in the XCode main toolbar.
XCode puts the .app file in the “build/Debug” and in the “build/Release” directories of the main project directory. In this case, in “build/Debug” (or “build/Release” if you have selected the “Release” configuration as the Active Build Configuration) there’s “Prova.app”.

The final application
This simply tutorial’s purpose is to introduce Cocoa’s neophites to a schematic way to approach to the development of a simply application.
Send me suggestions and corrections!
Click on the icon to download the project (created with XCode 3.1.2):



ciao!
Sono un programmatore molto in erba di obj-c…
ho un problema che non riesco a risolvere…se voglio che un button sia cliccabile solo una volta come posso fare?? so che esiste [Button setEnabled: NO]. Ma non so come si chiamano i pulsanti che ho posizionato su interface builder e come controllarli! Grazie mille in anticipo.
Se puoi rispondi via mail!
Ciao =)

E’ molto semplice, non ti preoccupare
In Interface Builder posizioni tutti i controlli che vuoi, senza preoccuparti di fare chissà che cosa. Poi posizioni un Object (lo trovi nella finestrina “Library” sotto “Cocoa/Objects & Controllers” ed è un cubo blu) nella finestra principale in cui sono elencati “Files’Owner”, “First Responder” etc.. devi fare come in quest’immagine:
Il passo successivo è dire al tuo object controller quale classe istanziare, e lo fai tramite l’Inspector (dal menù in alto di Interface Builder, clicchi su Tools->Inspector). Il nome deve corrispondere con il nome della classe che usi per controllare l’interfaccia: nel tutorial, ad esempio, ho creato un file ProvaController.m e ho deciso di usarlo come controller dell’interfaccia: il mio Object di Interface Builder sarà un’istanza della classe ProvaController (nell’immagine sopra è incluso anche questo passaggio).
Il passo finale è dire all’Object quali controlli (pulsanti, textlabel etc..) controllare (scusa il gioco di parole). Detto in parole povere, da interface builder tieni premuto il tasto control (Ctrl) e cliccando su di un pulsante (o textlabel che sia) tiri una linea fino all’Object. Comparirà un menù che elenca i nomi delle variabili di tipo NSButton (se stai linkando un pulsante) o di tipo NSTextField (se stai linkando un campo di testo): in pratica, gli dici di associare quel pulsante a quella variabile della classe ProvaController.
Infine fai il collegamento opposto, ovvero dal pulsante all’Object, e associ una determinata “funzione” al pulsante.
Ovviamente per far questo devi aver già scritto il codice della classe, in cui appunto crei delle variabili di tipo NSButton e NSTextField.
Per far sì che un controllo faccia qualcosa, devi creare dei metodi nella classe ProvaController, ovvero delle funzioni proprie di quella classe. In Cocoa, questi metodi si chiamano IBAction, e in pratica consentono di dialogare con l’interfaccia.
Ad esempio, hai un pulsante che istanzia la variabile “IBOutlet NSButton *button1click”. Vuoi fare in modo che, una volta cliccato, faccia le sue operazioni e poi venga disabilitato. In Interface Builder, colleghi l’object controller al pulsante (in modo da associare la variabile “button1click” a quel pulsante) e colleghi il pulsante all’Object (in modo da associare a “NSButton button1click” il metodo “(IBAction) mioPulsante:(id)sender”).
Se hai capito il meccanismo di collegamento interfaccia-codice, ti posto solo la funzione che serve a te, ovvero quella che disabilita il pulsante:
- (IBAction)vai_e_disabilita:(id)sender{
//Fai quello che vuoi
...
//Disabilito il pulsante
[button1click setEnabled:NO];
}
Spero di essere stato chiaro
Se ci sono problemi non ti preoccupare che posso provare a spiegartelo un po’ meglio =)
Ciao, ho un grosso dubbio che non riesco a risolvere. Io ho creato l’interfaccia del programma, ora voglio caricarci dei file che seleziono attraverso un NSOpenPanel, tale finestra modale la richiamo mediante il menù File –> Apri (classico) come faccio a passare l’array di percorsi dei file al mio programma?
In breve il mio problema più generalizzato sarebbe:
come passo dei dati di una classe ad un’altra?
Grazie Niko
Una cosa alla volta:
1) hai creato un’applicazione Cocoa document-based e quindi hai automaticamente il menù già pronto con tanto di apri, salva, undo e tutto il resto?
2) per “passare dei dati di una classe ad un’altra” devi utilizzare i metodi. La classe che “riceve i dati” deve essere abilitata per farlo, deve avere cioè un metodo che hai dichiarato tu nel codice e che hai implementato. Se la tua classe dispone di tale metodo, non ti basta che chiamare il metodo con un oggetto istanziato e passargli tutti gli argomenti che vuoi. Se quindi il tuo problema è “come faccio a creare dei metodi” allora posso risponderti.
Fammi sapere
Ciao, ho un problema relativo a ciò che hai indicato al punto 2) rispondendo a Niko, ovvero:
sto impazzendo per capire che codice usare per riuscire a visualizzare nella mia classeB il valore di una variabile stringa dichiarata nella mia classeA. Praticamente ho nella prima vista (classeA) 2 UITextField dove l’utente digita 2 nomi. Quando passo il controllo ad una seconda vista (classeB) vorrei appunto riuscire a recuperare il valore “text” delle 2 UITextField.
Mi sembrava una cosa molto semplice a livello logico ma ogni volta che provo ad accedere alla variabile mi restituisce “nil”.
Mi potresti dare una mano indicandomi il codice e la modalità corretta da utilizzare?
Grazie mille!!!!!
Ciao Andrea,
se ho capito bene stai parlando di iPhone. Non ho mai programmato per iPhone, però le cose funzionano sempre allo stesso modo.
Ti chiedo quindi di postarmi il codice che hai scritto, così riesco a capire meglio cosa intendi per “passare il controllo ad una seconda vista”.
Ciao Pietro,
si, in effetti parlavo proprio di iPhone.
Se mi potessi mandare sulla mia mail privata (che penso tu veda) il tuo indirizzo di posta elettronica, ti mando il codice zippato così ti viene più semplice…perchè c’è un po’ di roba!!!
Grazie mille…
Hi, i just followed your tutorial and managed to get it to work.
But i have a question, is there a way to remove a textfield?
Because i wanna go a little further and create and application where i have to login first and then go to another screen.
You may think about using view controllers. So you can manage different views, and for example use a view with the login box, and when the user clicks the login button, you unload that view and load a new view with some content inside.
Try to read about NSViewController.
To defenitely remove a textfield I think you can try this:
[theTextField setHidden:YES]; // OPTIONAL (hides the textfield)
[theTextField setEnabled:NO]; // OPTIONAL (disables the textfield)
[theTextField removeFromSuperviewWithoutNeedingDisplay]; // NOT OPTIONAL (removes the textfield from its superview safetly and releases it)
Ciao Pietro, complimenti per il tuo sito molto utile per i neofiti come me, ho letto i post precedenti e anke io in questa fase di apprendimento (molto base)nel programmare cocoa per iPhone, mi sono imbattuto nella necessità di passare dati di un array da una classe ad un altra e non riesco a trovare il metodo giusto….
in una classe tipo MainAppDelegate.m ho un array(che chiamerò Asso) in cui vengono copiati dei dati da un db sqlite, adesso per implementare una ricerca su questi dati devo copiare Asso in un Array di un altra classe che ho chiamato pippo. Io ovviamente sbagliando scrivevo dalla classe di ricerca [pippo addobjectsFromArray:[MainAppDelegate Asso]] mi puoi spiegare come implementare un metodo per risuscire nell’arcano?
grazie in anticipo! Mi sento come uno scolaretto alle prime domande sceme:)
Ciao Gianluca, ti ringrazio per i commenti positivi e sono contento che il sito ti sia d’aiuto =)
Dunque, vediamo di partire dall’inizio. Devi pensare ad una classe come ad un oggetto animato che ha vita propria. La tua classe ha delle proprietà (array, stringhe, numeri, oggetti) che condivide con l’esterno tramite dei metodi (setter e getter). In Objective-C hai diversi modi per creare questi getter e setter e quando vuoi accedere alle proprietà della classe dall’esterno, devi per forza pensare a questo modello logico. Una volta afferrato questo concetto, puoi pensare alla parte d’implementazione, nel senso che il getter di un numero non è come il getter di un oggetto (da un punto di vista della complessità e della memoria).
Per rendere tutto più semplice objective-c consente di sintetizzare formalmente la dichiarazione dei setter e getter tramite le properties, ossia quelle cosette strane:
@property (readwrite, copy) NSMutableArray *Asso; //nel .h@syntethize Asso; //nel .m
Scrivere quelle due righe è come scrivere:
//------------- nel .h...
@interface MainAppDelegate : NSObject
{
...
NSMutablerArray *_Asso;
...
}
-(NSMutableArray *)Asso; //getter
-(void)setAsso:(NSMutableArray *)anArray; //setter
//------------- nel .m
-(NSMutableArray *)Asso //getter
{
return _Asso;
}
-(void)setAsso:(NSMutableArray *)anArray //setter
{
[_Asso release];
_Asso = anArray;
}
E’ un altro modo di dire al compilatore la stessa cosa, solo che nel secondo caso puoi fare tante personalizzazioni. Di default se usi @property e @synthesize, xCode interpreta il tutto esattamente come ti ho scritto nella seconda versione; non c’è differenza tra le due. Ciò che cambia è nella direttiva readwrite, copy, atomic, nonatomic, retain. Queste direttive danno a xCode le regole su come comportarsi nei confronti del trattamento della variabile Asso (per maggiori informazioni leggi qui: http://www.cocoacast.com/?q=node/103 ).
Tornando a noi, il discorso diventa ora molto più semplice (se ho capito correttamente com’è strutturato il tuo programma e cosa devi fare).
– MainAppDelegate ha un array Asso.
– Pippo deve accedere ad Asso.
Di cos’hai bisogno?
1) MainAppDelegate deve disporre almeno di un metodo getter per la variabile Asso, cosicché sia possibile accedere da Pippo ad Asso
2) Ti serve l’istanza di MainAppDelegate che possiede l’array Asso contenete i valori di cui hai bisogno
Allora, cerchiamo di rispondere ai due punti:
1) In MainAppDelegate crei un metodo manualmente:
//in MainAppDelegate.h
-(NSMutableArray *)Asso;
//in MainAppDelegate.m
-(NSMutableArray *)Asso
{
return Asso;
}
2) Da Pippo, in un punto del codice, ottieni l’istanza di MainAppDelegate che t’interessa. Un modo per ottenerla (se hai reso MainAppDelegate il delegato dell’applicazione – come lascia intendere il nome MainAppDelegate) è di accedere a [[UIApplication sharedApplication] delegate] e poi da quest’oggetto puoi accedere al metodo getter Asso:
NSMutableArray *Asso = [NSMutableArray arrayWithArray:[[UIApplication sharedApplication] Asso]];e il gioco è fatto.
Spero di essere stato chiaro e di non aver fatto confusione, nonché di aver capito di cos’hai realmente bisogno. Se dovessi avere dubbi non esitare a chiedere
Ciao grazie per la spiegazione tempestiva e chiara, ora finalmente sto iniziando a comprendere meglio il meccanismo… ho fatto le modifiche, ma il compilatore mi da il seguente errore: sulla riga
NSMutableArray *antipasti = [NSMutableArray arrayWithArray:[[UIApplication sharedApplication] antipasti]];
antipasti sarebbe il nostro Asso.
/Users/Xenon/Documents/RicetteSQL copia 4/Classes/searchController.m:35:0 /Users/Xenon/Documents/RicetteSQL copia 4/Classes/searchController.m:35: warning: ‘UIApplication’ may not respond to ‘-antipasti’
/Users/Xenon/Documents/RicetteSQL copia 4/Classes/searchController.m:35:0 /Users/Xenon/Documents/RicetteSQL copia 4/Classes/searchController.m:35: warning: (Messages without a matching method signature
cmq in poche righe mi hai reso più comprensibile dei passaggi che in molti manuali online non sono molto chiari. Ti ringrazio di cuore.
Ciao, mi fa piacere se ti sono stato d’aiuto =)
Mi dici come hai dichiarato la property antipasti? Ti consiglio:
@property (readwrite, copy) NSMutableArray *antipasti;e anziché usare la notazione classica prova così:
NSMutableArray *antipasti = [NSMutableArray arrayWithArray:[UIApplication sharedApplication].antipasti];e se non funziona ancora prova:
NSMutableArray *antipasti = [NSMutableArray arrayWithArray:((MainAppDelegate *)[UIApplication sharedApplication]).antipasti];in ogni caso affinché la sharedApplication sia di tipo MainAppDelegate devi fare, in un punto del codice della classe MainAppDelegate, la seguente chiamata:
UIApplication.delegate = self;oppure lo fai da Interface Builder, ma funziona se in interface builder hai come File’s Owner la tua MainAppDelegate e quindi puoi collegare il delegato dell’applicazione al File’s Owner.
Se non dovessi capire chiedi pure chiarimenti =)
Ciao, la property era già [readwrite,copy], scrivendo:
NSMutableArray *antipasti = [NSMutableArray arrayWithArray:((MainAppDelegate *)[UIApplication sharedApplication]).antipasti];
non ho piu errori ma crascia , subito dopo aver eseguito la riga, con il messaggio :
[UIApplication antipasti]: unrecognized selector sent to instance 0×3b0a9b0
2010-03-16 12:32:28.253 RicetteSQL[1254:207] *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘*** -[UIApplication antipasti]: unrecognized selector sent to instance 0×3b0a9b0′
, stessa cosa se riscrivo:
NSMutableArray *antipasti = (NSMutableArray *)[(RicetteSQLAppDelegate *)[UIApplication sharedApplication ] antipasti];
RicetteSQLAppDelegate sarebbe la MainAppDelegate
antipasti è un NSMutableArray ke viene riempito con i dati letti dal db sqlite tramite un ciclo while e tramite breakpoint ho controllato il corretto inserimento dei dati, ho anche provato a eliminare il dealloc di antipasti… cmq l’app visualizza correttamente i dati nella TableView.
se inserisco nel – (void)applicationDidFinishLaunching:(UIApplication *)application:
UIApplication.delegate = self;
nell’RicetteSQLAppDelegate (lla vecchia MaiAppDelegate)
mi viene restituito il seguente errore dal compilatore:
RicetteSQLAppDelegate.m: In function ‘-[RicetteSQLAppDelegate applicationDidFinishLaunching:]‘:
RicetteSQL copia 4/Classes/RicetteSQLAppDelegate.m:46: error: accessing unknown ’setDelegate:’ class method
RicetteSQLAppDelegate.m:46: error: object cannot be set – either readonly property or no setter found
quasi quasi depenno la ricerca dalla mia applicazione
))))
Ciao ci sono riuscito!!!
Ovviamente grazie al tuo aiuto ho capito come comunicare tra classi, allora posto la soluzione per ki come me si ritrova a sbattere la testa sul monitor programmando iPhone, ricapitolando:
nella classe dove si trova la funzione in cui ho l’array (RicetteSQLAppDelegate) da cui devo leggere le informazioni inserisco una funzione che mi restituisce i dati (getter), nel mio caso:
-(NSMutableArray *)leggiAntipasti
{
return antipasti;
}
nelle property del.h ho lasciato (nonatomic, retain) per antipasti.
nella classe di ricerca ho inserito la seguente chiamata:
RicetteSQLAppDelegate *appDelegate= (RicetteSQLAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *antipasti =[appDelegate leggiAntipasti];
Fatto… per un programmatore provetto sembra una scemenza(e sicuramente scriverà codice + elegante), ma pe ki inizia sono soddisfazioni:)
Grazie PietroP
Mi fa molto piacere =)
).
Sì, penso che possa essere utile in futuro a chi come te avrà difficoltà ad affrontare questo aspetto della programmazione con Objective-C. Una volta capita la meccanica diventa tutto molto più semplice, soprattuto il discorso del delegate, delle properties e del concetto di classe come entità che interagisce con l’esterno e che ha vita propria.
Stavo giusto scrivendo un tutorial che da breve è diventato chilometrico, quindi ci metterò un po’ per ultimarlo. Mette insieme un po’ di cose, dalla strutturazione di una classe alle properties. Le basi logiche dello sviluppo nella programmazione ad oggetti (molto semplificate, non sono un professore
Buona programmazione e in bocca al lupo per il tuo progetto!
PS: se nel .h specifichi la property come @property (nonatomic, retain) NSMutableArray *antipasti; allora non devi necessariamente creare un metodo getter -(NSMutableArray *)leggiAntipasti, perché lo definisci implicitamente appena crei la @property. Se invece vuoi che il tuo getter sia “personalizzato”, ossia che non solo restituisca l’array ma che compia altre operazioni, allora è corretto come hai fatto tu. In ogni caso, è questione di comodità e praticità, in entrambi i casi ottieni la stessa cosa =)
wow, thanks very much, so simple and straight forward, even still works on old xcode 2.x!
thank you, i am just learning and this is really simple and useful!