Articoli con Tag ‘Objective-C’


Very short snippet: Objective-C, Selector from NSString

Objective-C è un linguaggio meraviglioso che permette di fare cose incredibili. Uno degli aspetti più interessanti è la sua dinamicità nell’invocazione di metodi (messaggi). È possibile, infatti, ottenere l’indirizzo di un messaggio partendo da una stringa.

Continua...

Very short snippet: UIWebView, visualizzare PDF e file interni

L’oggetto UIWebView può essere utilizzato per la visualizzazione di numerosi file. Ad esempio è possibile utilizzarlo per visualizzare – oltre che a filmati QuickTime o YouTube – documenti PDF o file HTML inseriti all’interno del nostro codice.

Continua...

Very short snippet: comporre mail all’interno di un’applicazione iPhone, iPod o iPad

Per comporre email all’interno di una applicazione iPhone/iPod è sufficiente aggiungere il framework MessageUI. Nel nostro controller inserire l’inclusione del framework e adottare il protocolo MFMailComposeViewControllerDelegate:

Continua...

Objective-C: metodi di classe e auto alloc

Quando definiamo o utilizziamo metodi (messaggi) in ambiente Objective-C, ci troviamo spesso di fronte alla curiosa sintassi che si presenta con un simbolo - o + davanti al prototipo, tipo:

1
2
3
4
5
6
7
// Nella definizione
- (void)mioMessaggio;

// Ugualmente, nell'implementazione
- (void)mioMessaggio {
    // ...
}

Oppure:

1
2
3
4
5
6
7
// Nella definizione
+ (void)mioMessaggio;

// Ugualmente, nell'implementazione
+ (void)mioMessaggio {
    // ...
}

La differenza risiede nel fatto che i metodi definiti con il simbolo - sono metodi di instanza, legati quindi ad un oggetto. I metodi definiti con il simbolo + sono chiamati metodi di Classe, in quanto possono essere eseguiti senza allocare ed istanziare l’oggetto in questione.

NSString o UIView sono due classi, molto usate, che contengono svariati metodi di classe. I metodi di classe vengono utilizzati continuamente, come quando inizializziamo o allochiamo un qualsiasi oggetto:

1
UIView *myView = [UIView alloc];

Il metodo alloc è un esempio classico, presente in tutti gli oggetti e, come si evince dal codice, è un metodo di classe in quanto invocato prima dell’allocazione dell’oggetto vero e proprio.

I metodi di classe possono essere utili in moltissimi casi, in particolare quando creiamo un nostro oggetto e desideriamo allocarlo ed inizializzarlo in meno righe di codice possibile. Immaginiamo di dover collezionare in un array una serie di oggetti da noi definiti. Definiamo prima di tutto il nostro oggetto, scrivendo il codice nel modo più semplice, senza utilizzare metodi di classe:

1
2
3
4
5
6
7
8
9
10
// Definizion l'interfaccia in myObject.h
#import <Foundation/Foundation.h>

@interface myObject : NSObject {
    NSString *name;
    NSString *lastname;
}

@property(nonatomic, retain) NSString *name;
@property(nonatomic, retain) NSString *lastname;

L’implementazione, nel caso più semplice, potrebbe risultare nulla o:

1
2
3
4
5
6
7
8
9
10
11
12
// myObject.m

#import "myObject.h"
@implementation myObject

@synthesize name, lastname;

- (void)dealloc {
    [name release];
    [lastname release];
    [super dealloc];
}

Quando andremo ad usare il nostro oggetto, ci troveremo ad utilizzare un codice simile a questo:

1
2
3
myObject *obj = [myObject alloc];
obj.name      = @"Mario";
obj.lastname  = @"Rossi";

Se volessimo creare numerosi oggetti di questo tipo, e inserirli in un NSArray, la situazione diventa un poco imbarazzante:

1
2
3
4
5
6
7
8
9
10
11
12
myObject *objA = [myObject alloc];
objA.name      = @"Mario";
objA.lastname  = @"Rossi";

myObject *objB = [myObject alloc];
objB.name      = @"Carlo";
objB.lastname  = @"Bianchi";

NSArray *elenco = [NSArray arrayWithObjects: objA, objB, nil];

[objA release];
[objB release];

Si potrebbe migliorare il codice creando un ciclo for o utilizzando un NSMutableArray per aggiungere man mano gli oggetti nel nostro elenco. Tuttavia la situazione migliorebbe di poco, in quando rimarrebbero fuori le impostazioni delle proprietà name e lastname. Verrebbe quindi spontaneo, per iniziare, aggiungere un metodo – di oggetto – initWithName che consentirebbe di passare immediatamente le impostazioni delle proprietà, semplificandoci un pochino le cose. Nel file di implementazione myObject.m aggiungiamo:

1
2
3
4
5
6
7
- (id)initWithName:(NSString *)stringName lastname:(NSString *)stringLastname {
    if ( self = [super init] ) {
        self.name = stringName;
        self.lastname = stringLastname;
     }
     return self;
}

Così facendo abbiamo migliorato la situazione, potendo ora scrivere:

1
2
3
4
5
6
7
myObject *objA = [[myObject alloc] initWithName: @"Mario" lastname: @"Rossi"];
myObject *objB = [[myObject alloc] initWithName: @"Carlo" lastname: @"Bianchi"];

NSArray *elenco = [NSArray arrayWithObjects: objA, objB, nil];

[objA release];
[objB release];

Abbiammo tuttavia ancora i puntatori objA e objB, necessari per l’inserimento nell’array e liberare la memoria. Volendo potremmo inserire direttamente la creazione di un oggetto nel popolamento dell’array, utilizzando autorelease per liberare la memoria, ma il codice sarebbe ancora non al minimo. Lasciatemi mostrare come risolvere la questione con un metodo di classe. Prima di tutto sostituiamo la nostra - (id)initWidthName con:

1
2
3
4
5
6
7
8
9
10
+ (id)initWithName:(NSString *)name lastname:(NSString *)lastname {
    myObject *item;
 
    if ( item = [[self alloc] init] ) {
        // Init
        item.name = name;
        item.lastname = lastname;
    }
    return [item autorelease];
}

Così facendo abbiamo creato un metodo di classe che alloca (in autorelase) e iniziallizza un nostro oggetto, prima di avere il puntatore all’istanza. Il codice di utilizzo diventa quindi:

1
2
3
4
NSArray *elenco = [NSArray arrayWithObjects:
    [myObject initWithName: @"Mario" lastname: @"Rossi"],
    [myObject initWithName: @"Carlo" lastname: @"Bianchi"],
    nil];

Molto, molto meglio…

Continua...

WordPress Plugin Maker

Sono davvero felice di poter presentare in anteprima assoluta WordPress Plugin Maker, un applicativo per Mac OS X (Snow Leopard) che permette di creare uno scheletro di un Plugin WordPress in pochi secondi, permettendo di impostare numerosi parametri. L’applicazione è ancora in fase di sviluppo, tuttavia esegue il suo compito base ed è tranquillamente usabile e funzionale. Alcune funzionalità non sono ancora state inserite ed altre le si attendono dai feedback dei “pochi” fortunati beta tester.

Continua...

Come ottenere Latitudine e Longitudine in Objective-C

Il MapKit framework fornisce moltissime funzionalità utili, tranne quella di restituire Longitudine e Latitudine a partire da un indirizzo. In Javascript, ad esempio, è possibile utilizzare il servizio di Geocoding fornito da Google e discusso in Google Maps: come ottenere Latitudine e Longitudine da un indirizzo. Su Apple iPhone, o iPad, è possibile tuttavia superare l’ostacolo utilizzando in modo diverso i servizi di Google. Nello specifico è possibile chiamare direttamente l’url:

1
http://maps.google.com/maps/geo?q=[indirizzo]&output=csv

Dove è [indirizzo] inserire la stringa con l’indirizzo che vogliamo trasformare in coordinate. L’output restituito è del tipo:

1
200,8,41.9128300,12.2241172

Il primo valore, 200, indica che tutto è andato bene (200 OK). Il secondo, 8, è il Google accuracy parameter (1-10). Gli ultimi due valori sono, finalmente, latitudine e longitudine. Vediamo adesso un possibile prototipo di un metodo da inserire nelle nostre applicazioni:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (CLLocationCoordinate2D)getLocationFromAddress:(NSString*)address {
    NSString *urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv",
          [address stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
    NSString *locationString = [[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]] autorelease];
    NSArray *listItems = [locationString componentsSeparatedByString:@","];
 
    //int zoom       = 0;
    double latitude  = 0.0;
    double longitude = 0.0;
 
    if([listItems count] >= 4 && [[listItems objectAtIndex:0] isEqualToString:@"200"]) {
        //zoom    = [[listItems objectAtIndex:1] intValue];
        latitude  = [[listItems objectAtIndex:2] doubleValue];
        longitude = [[listItems objectAtIndex:3] doubleValue];
    } else {
        // Errore
    }
    CLLocationCoordinate2D location;
    location.latitude  = latitude;
    location.longitude = longitude;
 
    return location; 
}

Note interessanti

La stringa restituita in locationString viene “splittata” tramite il metodo componentsSeparatedByString, alla stregua della funzione explode() del PHP per intenderci. Nell’esempio da me proposto ho inserito – ma commentato – il codice per recuperare anche il Google accuracy parameter, o fattore di scala di precisione, indicato con zoom.

Sorgente esempio

Per completezza ho realizzato un piccolo applicativo di esempio con il quale è possibile provare il metodo sopra proposto; inserite un qualsiasi indirizzo e iPhone lo mostrerà sulla mappa.


Scarica Sorgente

Ringrazio il team di devAPP per l’ispirazione di questo articolo.

Continua...

setAnimationDidStopSelector: usi diversi ed avanzati

Nella maggioranza dei casi, o perchè siamo abituati o perchè l’abbiamo visto in tutorial e in alcuni testi, utilizziamo il setAnimationDidStopSelector in questa maniera:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(removeView)];
 
myView.alpha = 0;
 
[UIView commitAnimations];

//

- (void) removeView {
    [myView removeFromSuperview];
}

Nel codice sopra esposto la setAnimationDelegate imposta self come delegato e tramite la setAnimationDidStopSelector gli invia un messaggio removeView quando l’animazione è terminata. Il codice è di per sé corretto, tuttavia fa uso di una definizione di messaggio (removeView) che potrebbe essere omessa. Guardate adesso lo stesso codice, con il medesimo effetto, senza il messaggio removeView:

1
2
3
4
5
6
7
8
9
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:myView];
[UIView setAnimationDidStopSelector:@selector(removeFromSuperview)];
 
myView.alpha = 0;
 
[UIView commitAnimations];

La cosa interessante di questo approccio è che myView potrebbe essere una sottoclasse di una UIView! Potrebbe quindi essere una nostra classe personalizzata con propri messaggi ed, nel modo esposto, tranquillamente richiamabile da setAnimationDidStopSelector. Inoltre, la setAnimationDidStopSelector accetta selettori con parametri:

1
2
3
4
5
6
7
8
9
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:myView];
[UIView setAnimationDidStopSelector:@selector(myMessage:param1:)];
 
myView.alpha = 0;
 
[UIView commitAnimations];

Questo esempio può essere esteso a tutti qui casi dove impostiamo un delegato che, atro non è, che un puntatore ad un’istanza di un oggetto qualsiasi.

Continua...

Come localizzare immagini e viste di Interface Builder

Dopo aver illustrato come localizzare le nostre stringhe in Xcode, vediamo adesso quanto risulta semplice – applicando la medesima tecnica – localizzare immagini e viste/interfacce realizzate con Interface Builder.

Localizzare risorse grafiche

Il processo, come accennato, è il medesimo; se abbiamo un’immagine già inserita nelle nostre risorse, o ne inseriamo una nuova, e vogliamo “localizzarla” – cioè gestire due o più immagini in base alle lingue supportate – basterà cliccare con il tasto destro sull’immagine (Adium.png in questo esempio) e selezionare Get Info:

Clicchiamo Make File Localizable in basso a sinistra.

Clicchiamo su Add Localization e inseriamo Italian:

In modo da ottenere:

La nostra immagine viene spostata (fisicamente, una delle rare volte in cui quello che accade nell’alberatura Xcode si riflette sul filesystem) sotto le cartelle virtuali English.lproj e Italian.lproj esattamente come accadeva con il testo:

A questo punto ognuna delle cartelle English.lproj e Italian.lproj contiene una stessa versione dell’immagine. Questa immagine è manipolabile all’interno di Interface Builder, dove ne vedremo – per default – la versione inglese.
Arrivati a questo punto, basta sovrascrivere uno (o entrambi i file Adium.png) per ottenere una localizzazione delle immagini “lampo”.

Localizzare i file XIB

Anche le interfacce costruite con Interface Builder possono essere localizzate nella loro interezza, quando lo si ritiene necessario. Il procedimento è identico a quello svolto con le risorse grafiche: aggiungiamo un ViewController (ad esempio infoViewController) con interfaccia XIB, lo selezioniamo, scegliamo Get Info dal menu contestuale, rendiamo il file localizzabile, aggiungiamo la localizzazione in italiano:

ViewController

Cliccando su English o su Italian si aprirà Interface Builder! Questa volta, sul filesystem, noteremo che sono state create due cartelle (English.lproj e Italian.lproj) all’interno della classica cartella Classes. Entrambe avranno il loro file infoViewController.xib. La comodità, in questo, risolta evidente nel codice; quando andremo ad istanziare il nostro controller si avrà un codice “pulito” di questo tipo:

1
2
InfoViewController *info = [InfoViewController alloc];
[self.view addSubview:info.view];

Come vedete non c’è traccia di nessuna dichiarazione relativa alla localizzazione, totalmente gestita da sistema. Le due interfacce, ovviamente, possono essere completamente differenti, in quanto risultano a tutti gli effetti come due file XIB separati.

Continua...

Come creare un proprio protocollo con delegato

Anche nei tutorial più semplici è possibile incontrare l’uso dei protocolli. Sarà certamente capitato a molti di utilizzare nel vostro view controller un protocollo, inserendo, accanto alla definzione dell’interfaccia, una dicitura simile a:

1
2
3
@interface myViewController : UIViewController <uiwebviewdelegate> {
...
}

Continua...

Very short snippet: ottenere l’output di un URL in Objective-C

Avrei forse dovuto scrivere “Very very very, short snippet”, tuttavia è un ottimo e comodissimo “trucchetto” questo che sto per mostrare. Eseguendo le “due” righe di codice indicate qui sotto, è possibile ottenere l’output di qualsiasi URL e manipolarlo.

Continua...



Stop SOPA