Archivio giugno, 2009


Job in saidmade: cercasi programmatore

Saidmade srl, nonostante il momento apparentemente di crisi, offre una grande opportunità ai giovani appassionati di informatica. L’offerta di lavoro è concreta, indirizzata a tutti coloro che desiderano svolgere l’attività di sviluppatore, una professione che richiede passione e grande volontà, spesso sottovalutata soprattutto qui in Italia. La società di cui sono socio, quindi, è alla ricerca di un programmatore/programmatrice Junior con i seguenti requisiti:

  • Età compresa fra i 18 e i 27 anni e una buona dose di creatività
  • Conoscenza di base della programmazione e soprattutto del linguaggio ANSI-C

Volontà di acquisire conoscenza su:

  • Programmazione OO
  • PHP
  • Javascript
  • Adobe Actionscript
  • C++ / Objective-C

Costituisce, inoltre, titolo preferenziale la conoscenza d:

  • XHTML / CSS
  • WordPress

Se il vostro profilo e il vostro interesse trovano riscontro in quanto detto sopra, inviate la vostra proposta di condidatura a: info@saidmade.com

Continua...

Eclipse, Aptana: upload file tramite tastiera

L’IDE Aptana è disponibile anche come Plugin per Eclipse. Una delle caratteristiche più apprezzate di questo ambiente è l’ottima gestione del FTP e la sincronizzazione dei file/progetti locali con il remoto. In particolare esiste uno script che permette di inviare il codice attualmente nella finestra di editor al server remoto, tramite la combinazione dei tasti CONTROL+SHIFT+U o COMMAND+SHIFT+U su Mac OS (la stessa combinazione è usata in Adobe Dreamweaver). In alcune installazioni (ad esempio la mia su Mac OS, Eclipse e Aptana com Plugin) tale combinazione sembra assente e, se cercate di rintracciarla nelle Preferences > General > Keys non troverete – misteriosamente – nulla! Il problema, tuttavia, è facilmente risolvibile e dipende dalla sovrapposizione di un’altra impostazione. Risulta, infatti, che la combinazione dei tasti sopra citati è impostata per default su un’altra funzione: Shows Occurrences in File Quick Menu. Quindi basta aprire il pannello delle Preferences > General > Keys e cercare shows occ..:

eclipseprefs

Rimuivere il “binding”, cioè l’associazione con lo shortcut da tastiera, e tutto funzionerà!

Continua...

iPhone: tutti i font di sistema

L’Apple iPhone mette a disposizione un numero limitato di Font agli sviluppatori. La lista dei font disponibili è facilmente ottenibile da codice, come vedremo. Se volete usare un vostro font, ad esempio includendolo nelle risorse, la cosa è un pochino più articolata e conivolge anche la questione delle licenze (diritti) sui font “embeddati”… ne riparleremo in seguito. Tornando invece ai font ufficiali presenti nell’Apple iPhone questi sono (cliccate sull’immagine per ingrandire):

iphonefonts

L’SDK di Apple iPhone permette di accedere a degli speciali font di sistema. Questi sono identificati da particolari costanti e sono:

1
2
3
UIFont *myBoldFont   = [UIFont boldSystemFontOfSize:12.0];
UIFont *mySystemFont = [UIFont SystemFontOfSize:12.0];
UIFont *myItalicFont = [UIFont italicSystemFontOfSize:12.0];

Se volete invece ottenere un puntatore ad uno odei font mostrati nell’immagine di sopra basta usare:

1
UIFont *myCustomFont = [UIFont fontWithName:@"Helvetica-Bold" size:22.0];

Come avrete notato la gestione del font è particolare; oltre alla famiglia (Helvetica, Courier, etc…) bisogna specificare il tipo (bold, italic, etc…). In pratica, quindi, un font deve essere fornito di queste caratteristiche. L’Helvetica, ad esempio, è presente con:

1
2
3
4
Helvetica
Helvetica-Bold
Helvetica-Oblique
Helvetica-BoldOblique

Se volete visualizzare direttamente i vostri font sull’iPhone, ecco qualche linea di codice utile:

1
2
3
4
5
6
7
8
9
10
11
12
NSArray *listOfFonts = [[NSArray alloc] initWithArray:[UIFont familyNames]];
NSArray *subFontTypes;

for (int i=0; i<[listOfFonts count]; i++) {
    NSLog(@"Font Family: %@", [listOfFonts objectAtIndex:i]);
    subFontTypes = [[NSArray alloc] initWithArray:[UIFont fontNamesForFamilyName:[listOfFonts objectAtIndex:i]]];
    for (int j=0; j<[subFontTypes count]; j++) {
        NSLog(@"+----->Type: %@", [subFontTypes objectAtIndex:j]);
    }
    [subFontTypes release];
}
[listOfFonts release];

Con le SDK 2.2.1, sul mio simulatore, ho ottenuto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Font Family: Courier
+----->Type: Courier
+----->Type: Courier-BoldOblique
+----->Type: Courier-Oblique
+----->Type: Courier-Bold
Font Family: AppleGothic
+----->Type: AppleGothic
Font Family: Arial
+----->Type: ArialMT
+----->Type: Arial-BoldMT
+----->Type: Arial-BoldItalicMT
+----->Type: Arial-ItalicMT
Font Family: STHeiti TC
+----->Type: STHeitiTC-Light
+----->Type: STHeitiTC-Medium
Font Family: Hiragino Kaku Gothic ProN
+----->Type: HiraKakuProN-W6
+----->Type: HiraKakuProN-W3
Font Family: Courier New
+----->Type: CourierNewPS-BoldMT
+----->Type: CourierNewPS-ItalicMT
+----->Type: CourierNewPS-BoldItalicMT
+----->Type: CourierNewPSMT
Font Family: Zapfino
+----->Type: Zapfino
Font Family: Arial Unicode MS
+----->Type: ArialUnicodeMS
Font Family: STHeiti SC
+----->Type: STHeitiSC-Medium
+----->Type: STHeitiSC-Light
Font Family: American Typewriter
+----->Type: AmericanTypewriter
+----->Type: AmericanTypewriter-Bold
Font Family: Helvetica
+----->Type: Helvetica-Oblique
+----->Type: Helvetica-BoldOblique
+----->Type: Helvetica
+----->Type: Helvetica-Bold
Font Family: Marker Felt
+----->Type: MarkerFelt-Thin
Font Family: Helvetica Neue
+----->Type: HelveticaNeue
+----->Type: HelveticaNeue-Bold
Font Family: DB LCD Temp
+----->Type: DBLCDTempBlack
Font Family: Verdana
+----->Type: Verdana-Bold
+----->Type: Verdana-BoldItalic
+----->Type: Verdana
+----->Type: Verdana-Italic
Font Family: Times New Roman
+----->Type: TimesNewRomanPSMT
+----->Type: TimesNewRomanPS-BoldMT
+----->Type: TimesNewRomanPS-BoldItalicMT
+----->Type: TimesNewRomanPS-ItalicMT
Font Family: Georgia
+----->Type: Georgia-Bold
+----->Type: Georgia
+----->Type: Georgia-BoldItalic
+----->Type: Georgia-Italic
Font Family: STHeiti J
+----->Type: STHeitiJ-Medium
+----->Type: STHeitiJ-Light
Font Family: Arial Rounded MT Bold
+----->Type: ArialRoundedMTBold
Font Family: Trebuchet MS
+----->Type: TrebuchetMS-Italic
+----->Type: TrebuchetMS
+----->Type: Trebuchet-BoldItalic
+----->Type: TrebuchetMS-Bold
Font Family: STHeiti K
+----->Type: STHeitiK-Medium
+----->Type: STHeitiK-Light

Continua...

Come eliminare NSLog() dai sorgenti XCode

<a target="_blank" href="http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSLog">NSLog()</a> è una funzione utilissima durante le fasi iniziali di un progetto, per il testing e il debug di un’applicazione per Apple iPhone o, più in generale, in ambiente XCode. Essendo appunto una funzione, esattamente come le altre, la sua presenza si farà sentire anche quando rilasceremo (release) il nostro eseguibile. Diventa quindi necessario rimuovere, in qualche modo, tutte le righe di NSLog() dal nostro codice, sia perchè non più necessarie, sia perchè le chiamate a NSLog() potrebbero influire sulle performance della nostra applicazione, soprattutto se abbiamo inserito NSLog() all’interno di loop.

Escludiamo subito la soluzione del “cerca” ed “elimina”; perchè un domani ci potrebbero servire nuovamente. Escludiamo anche la soluzione del “cerca” e “commenta”, scomoda per lo stesso motivo di prima. Fortunatamente una soluzione pulita, semplice e corretta la troviamo sfruttando le istruzioni condizionali del compilatore. Quello che faremo, in pratica, e dire al compilatore di escludere – se si verifica una determinata condizione – durante la compilazione del nostro sorgente le righe che contengono NSLog().

Le direttive di compilazioni e le istruzioni condizionali del compilatore, sono uno strumento molto potente e diffuso. Chi proviene dallo sviluppo ANSI-C le conosce sicuramente molto bene e le avrà utilizzte in moltissime situazioni. La particolarità di queste “istruzioni” risiede nel fatto, sopra accennato, di essere viste dal compilatore e non dall’eseguibile. Questa loro caratteristica le rende utili in moltissimi casi e permette di risolvere problematiche altrimenti assai fastidiose.

Vediamo subito un esempio di codice che, come preannunciato, permette di “eliminare” dalla compilazione parti di codice, nel nostro caso NSLog():

1
2
3
4
5
6
#define ACTIVE_NSLOG 1
// se la costante ACTIVE_NSLOG è definita compila
// il blocco di codice compreso tra #ifdef e #endif
#ifdef ACTIVE_NSLOG
    NSLog( @" ... bla bla" );
#endif

Le istruzioni condizionali del compilatore fanno parte della stessa famiglia della #define; anch’esse, infatti, sono precedute dal carattere “cancelletto” (#). Nell’esempio mostrato abbiamo definito una costante ACTIVE_NSLOG; le successive righe di codice dicono al compilatore di “includere” la riga NSLog() solo se ACTIVE_NSLOG è definito. Se abbiamo avuto la cura, durante la stesura del nostro codice, di inserire le chiamate a NSLog() all’interno del blocco #ifdef ... #endif, basterà eliminare la definizione della costante ACTIVE_NSLOG per far sparire, alla prossima compilazione, tutti i nostri NSLog().

Una soluzione migliore e definitiva

Vediamo adesso come impostare l’ambiente XCode per migliorare ancor di più ciò che abbiamo fatto sopra! Prima di tutto scegliamo un nome di costante che useremo nei nostri progetti per escludere dalla compilazione NSLog(). Potete scegliere il nome che più vi piace, da DEBUG a MIO_DEBUG o quello che preferite. Aprite il vostro progetto, nuovo o vecchio. Inserite tutti gli NSLog() all’interno del blocco (o di un blocco):

1
2
3
#ifdef MIO_DEBUG
    NSLog( @" ... bla bla" );
#endif

Selezionate il file principale del vostro progetto, cliccate con il tasto destro e scegliete la voce Get Info.

getinfo

Si aprira la finestra con le informazioni sul progetto:

userdefine

Selezionate la scheda Build, verificate di essere in configurazione Debug (è questa la chicca), andate nella sezione User-Defined e aggiungete, tramite il bottone in basso a sinistra, un nuovo campo chiamato OTHER_CFLAGS. A questo assegnamoli il valore -DMIO_DEBUG=1. La sintassi è -D{mia define}=1.

Questa procedura ha due vantaggi:

  1. Non dobbiamo inserire nel codice la #define MIO_DEBUG 1, ma lo facciamo tramite le informazioni sul progetto. Quindi, quando andremo a compilare la versione di rilascio (quella senza gli NSLog()) non dobbiamo ricordarci di eliminare la riga #define MIO_DEBUG 1
  2. La costante è definita in relazione alla configurazione, nel nostro caso Debug. Quindi, passando alla configurazione di rilascio (release) la costante sarà assente e le righe con NSLog() non verranno compilate

Conclusioni

La procedura sopra descritta può essere utile in una moltidutine di altri casi che, con NSLog(), non hanno nulla a che fare. Le istruzioni condizionali del compilatore possono aiutarci in una vastissima gamma di contesti. Spesso sono utilizzate dai programmatori per determinare il tipo di sistema operativo, la versione, il target, la presenza di processori matematici, mantenendo uno stesso “identico” sorgente.

Per capirci, come esempio, possiamo utilizzre la nostra costante MIO_DEBUG anche per intervenire in altre zone del codice:

1
2
3
4
5
6
7
8
9
10
// se sono in debug vinco la partita
// con uno score di 100 invece che di 10000 :)
#ifdef MIO_DEBUG
    if( score == 100 )
#else
    if( score == 10000 )
#endif
    {
        [self haiVinto];
    }

Per completare, ecco alcuni esempi e varianti:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// più in generale esiste la
#if espressione
// simile alle if tradizionali, quindi con una espressione completa

// verifica se è definita una costante
#ifdef costante

// verifica se NON è definita una costante
#ifndef costante

// else
#else

// chiusura del blocco
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ad esempio...
#define DEBUG 1
#define MIA_ALTRA_COSTANTE 5
 
...
#if DEBUG
  // compila questo
#else
  // altrimenti compila quest'altro
#endif
 
#if MIA_ALTRA_COSTANTE > 4
  NSLog(@"...");
#endif
1
2
3
4
#ifndef INCLUDE_MIO_FILE
    #define INCLUDE_MIO_FILE
    #include "mio_file.h"
#endif

Continua...

iPhone FirstApp: indovina il numero – parte 1

Il primo sorgente che mi è passato tra le mani era scritto in Basic e consisteva in poche righe di codice, per me illuminanti. Era un semplice giochino che generava un numero casuale da 1 a 10 e, tramite l’input da tastiera, verificava che il numero inserito era maggione, minore o uguale al numero casuale. Nonostante la sua rozza semplicità rimane, per me, uno dei migliori esempi – semplici, divertenti e pratici – per spiegare a chi non sa nulla di programmazione cosa s’intenda effettivamente per “programma per computer”. Così ho pensato di riproporlo per Apple iPhone, magari aiuterà qualcuno…

Continua...

Objective-C: conversione dei tipi

Con alcuni linguaggi ad alto livello, come Javascript o PHP, dove i dati non sono tipizzati o comunque possono non esserlo, siamo “viziati” nel confrontare o trasformare interi e stringhe e vice versa, il tutto nascosto o manipolato dall’interprete (o compilatore). Ad esempio in Javascript esistono funzioni di “forzatura” (come parseInt() ad esempio) necessarie in particolari casi. Tuttavia in altre circostanze trattiamo gli interi senza preoccuparci di particolari conversioni (esplicite), come ad esempio:

1
2
3
var mioNumero = 5;
// ...
alert( "Il valore di mioNumero è " + mioNumero );

In Objective-C, invece, il tipo dato è importante e la conversione di tipo dev’essere esplicita. Oltra al casting (meglio typecasting) ci possiamo avvalere di funzioni e funzionalità specifiche per la conversione di tipo. Ad esempio ecco come convertire un intero in stringa:

1
2
3
4
int mioNumero = 5;
NSString *miaStringa = [NSString stringWithFormat:@"%d", mioNumero];
//
NSLog(@"miaStringa=%@ mioNumero=%i", miaStringa, mioNumero);

Al contrario, ecco come convertire una stringa in intero:

1
2
3
4
NSString *miaStringa = @"128";
int mioNumero = [miaStringa integerValue];
//
NSLog(@"miaStringa=%@ mioNumero=%i", miaStringa, mioNumero);

Continua...

iPhone code snippet: UIAlertView

La classe UIAletrView permette di mostrare una finestra modale (animata) per informare e/o chiedere qualcosa all’utente. Le UIAlterView (viste alert) sono molto comode e semplici da usare. Anche la gestione della risposta utente viene risolta intercettando l’indice del bottone premuto. Per visualizzare un semplice UIAlterView basta scrivere:

1
2
3
4
// semplice Alert con un bottone, senza callback
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo" message:@"Messaggio" cancelButtonTitle:@"Annulla" otherButtonTitles: nil];
[myAlert show];
[myAlert release];

E’ possibile aggiungere ulteriori bottoni in otherButtonTitles:

1
2
3
4
// semplice Alert con due bottoni, senza callback
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo" message:@"Messaggio" cancelButtonTitle:@"Annulla" otherButtonTitles:@"Ok", nil];
[myAlert show];
[myAlert release];

Per determinare quale bottone è stato premuto, basta aggiungere la delegate:self nell’inizializzazione dell’oggetto UIAlterView:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// semplice Alert con due bottoni e callback
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo" message:@"Messaggio" delegate:self cancelButtonTitle:@"Annulla" otherButtonTitles:@"Ok", nil];
[myAlert show];
[myAlert release];

// la callback ha questa sintassi

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    switch ( buttonIndex ) {
        case 1:
            // codice
            break;
    }
}

La callback alertView deve avere necessariamente quel nome; per maggiori informazioni vedi UIAlertViewDelegate

Avendo a disposizione solo la callbck alertView:clickedButtonAtIndex, più UIAletrView punteranno sempre a quella. Utilizzando il campo tag dell’oggetto UIAletrView, possiamo determinare quale sia il “chiamante”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// semplice Alert con due bottoni e callback
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo" message:@"Messaggio" delegate:self cancelButtonTitle:@"Annulla" otherButtonTitles:@"Ok", nil];
myAlertA.tag = 1;
[myAlertA show];
[myAlertA release];

//
UIAlertView *myAlertB = [[UIAlertView alloc] initWithTitle:@"Titolo" message:@"Messaggio" delegate:self cancelButtonTitle:@"Annulla" otherButtonTitles:@"Ok", nil];
myAlertA.tag = 2;
[myAlertB show];
[myAlertB release];

// gestione multipla UIAlertView

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    NSLog(@"Alert Tag: %i", alertView.tag);
    NSLog(@"buttonIndex: %i", buttonIndex);
}

Continua...

iPhone Objective-C: equivalenza nella sintassi

La sintassi con le parentesi quadre in Objective-C è uno dei motivi di maggior frustazioni per chi proviene da altri linguaggi (ad oggetti). Tuttavia, fatta l’abitudine, ci si rende conto di quanto il codice diventi ugualmente leggibile con questa il mix della sintassi classica e quella più spiccatamente Smalltalk. Ad esempio vediamo come la stessa procedura può essere scritta in entrambe le sintassi. Prendiamo l’inizializzazione di un UIAlertView:

1
2
3
4
5
6
7
8
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo"
                                            message:@"Messaggio"
                                            delegate:self
                                            cancelButtonTitle:@"Annulla"
                                            otherButtonTitles:@"Ok",nil];
myAlert.tag = 1;
[myAlert show];
[myAlert release];

L’impostazione del tag potavamo farla anche così:

1
2
3
4
5
6
7
8
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle:@"Titolo"
                                            message:@"Messaggio"
                                            delegate:self
                                            cancelButtonTitle:@"Annulla"
                                            otherButtonTitles:@"Ok",nil];
[myAlert setTag:1];
[myAlert show];
[myAlert release];

Stessa cosa in lettura durante l’evento:

1
2
3
4
5
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if( alertView.tag == 1 ) { // ...
    // oppure
    if ([alertView tag] == 1) { // ...
}

Nota bene: non tutte le proprietà o metodi hanno questa duplice sintassi. Nel caso dell’UIAlertView abbiamo questa doppia funzionalità. Per altri oggetti o in altri casi, invece, potrebbero funzionare una sola delle due… ma non chiedetevi perchè (dipende da come gli sviluppatori hanno definito l’interfaccia).

Continua...

Actionscript trace, Objective-C NSLog()

Riprendendo il post Da Actionscript ad Objective-C (dove si mettevano a confronto il codice e la sintassi Actionscript e Objective-C), in Actionscript abbiamo la comodissima funzione trace(), usata per il debug delle applicazioni. Questa funzione emette un output sulla console dell’ambiente di sviluppo Adobe Flash. Viene utilizzata principalmente nelle fasi di sviluppo e testing di “filmato”/applicativo. In XCode/Objective-C abbiamo: NSLog(). La sintassi di questa funzione è molto simile alla trace() di Actionscript:

1
NSLog( @"Sono una linea di debug" );

In Actionscript avremmo:

1
trace( "Sono una linea di debug" );

A parte l’uso della chiocciola (@), come potete vedere, sono identiche. Le differenze (e similitudini) iniziano quando si vogliano visualizzare valori di variabili; ad esempio in Actionscript potremmo avere:

1
2
3
trace( "Coordinata x:" + x + " coordinata y:" + y );
// oppure
trace( "Coordinate: ", x, y );

In Objective-C abbiamo:

1
NSLog( @"Coordinata x:%i coordinata y:%i", x, y );

Nota: NSLog() in realtà richiama la più generica funzione NSLogv() che opera sull’Apple System Log. Le funzioni sono di fatto identica, cambiano solo i parametri in ingresso.

Gli sviluppatori C troveranno molto familiare la formattazione delle stringhe, come accade per printf() o sprintf(). Per dettagli si veda String Format Specifiers.

Continua...

Very short trick: fermare NSTimer

L’uso dei timers (NSTimer) nello sviluppo di applicazioni per Apple iPhone è molto frequente e non solo nella realizzazione di giochi. Uno dei problemi con cui ci si può scontrare è l’asincronicità del timer stesso, che può portare, durante l’arresto di uno o più timer, al crash della nostra applicazione. Quando si vuole fermare uno o più timer, nei casi in cui repeats è impostato a YES, si invoca la invalidate che, appunto, arresta il timer.

Continua...