Categoria ‘Objective-C’


Very short snippet: registrare un’immagine nel Photo Album

Semplice modo per salvare nell’album fotografico del dispositivo un’immagine presente all’interno della nostra applicazione (o caricata da remoto):

Continua...

NSURLConnection: esempio d’uso

NSURLConnection permette di eseguire una connessione cotrollata verso un server remoto. Per utilizzarlo basta:

1
2
3
4
5
6
7
8
9
10
11
// Gli oggetti sufficienti per eseguire una NSURLConnection
NSURLConnection *urlConnection;
NSMutableData *mutableData;

// ...

NSString *urlString = @"http://www.miodominio.com/documento.txt";

NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString: urlString]];
// Il delegato risponderà agli stati della connessione
urlConnection = [[NSURLConnection alloc] initWithRequest: urlRequest delegate:self];

Ecco i metodi delegati per controllare lo stato della connessione:

[cc_objc]

Continua...

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...

NSString

NSString è una classe potentissima, lasciatemi mostrare alcune delle proprietà più utilizzate:

printf()

1
2
// printf()
NSString *output = [NSString stringWithFormat:@"%@ / %@", @"primo", @"secondo"];

Eseguire lo split()

1
2
3
// split() / explode()
NSString *list = @"Norman, Stanley, Fletcher";
NSArray *listItems = [list componentsSeparatedByString:@", "];

Convertire da stringa a valore

1
2
3
// converting
NSString *doubleString = @"123";
double value = [doubleString doubleValue];

All’interno di una stringa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// substring
NSString *searchString = @"age";
 
NSString *beginsTest = @"Agencies";
NSRange prefixRange = [beginsTest rangeOfString:searchString
    options:(NSAnchoredSearch | NSCaseInsensitiveSearch)];
 
// prefixRange = {0, 3}
 
NSString *endsTest = @"BRICOLAGE";
NSRange suffixRange = [endsTest rangeOfString:searchString
    options:(NSAnchoredSearch | NSCaseInsensitiveSearch | NSBackwardsSearch)];
 
// suffixRange = {6, 3}

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...

iPad: gestire le schermate d’avvio

Su Apple iPhone e iPod eravamo abituati a gestire un solo file immagine al caricamento dell’applicazione, il file Default.png. Su Apple iPad, invece, la diversa gestione dell’orientamente impone l’adozione di più file immagine, per essere certi di visualizzare lo splash screen corretto in base all’orientamente del dispositivo. Durante l’avvio dell’applicazione, come accadeva per iPhone, non è infatti possibile intervenire da codice per “chiedersi” com’è orientato il dispositivo. Fortunatamente è stato introdotto in automatico il caricamento di speciali file a seconda dell’orientamento:

I file attualmente supportati, oltre al classico Default.png che sconsiglio di utilizzare in quanto viene ridimensionato e deformato in base all’orientamento, sono:

  • Default-Portrait.png
  • Default-PortraitUpsideDown.png
  • Default-Landscape.png
  • Default-LandscapeLeft.png
  • Default-LandscapeRight.png

Le versioni PortraitUpsideDown, LandscapeLeft e LandscapeRight possono essere utilizzate per determinare orietamento e verso di quest’ultimo.

Ad applicazione avviata, poi, come consigliato da Apple, è bene “ridisegnare” – ove necessario – le nostre viste agendo all’interno di application:didFinishLaunchingWithOptions.

Continua...

Personalizzare le sezioni in un UITableView Grouped

Quando utilizziamo una UITableView in stile Grouped potremmo aver necessità di personalizzare la grafica dei titoli delle sezioni, come California o New York dell’esempio qui sotto.

UITableView

Per farlo basta utilizzare il codice seguente, inserendolo nel delegato, cioè nella classe che risponde al protocollo UITableViewDelegate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Restituisco una mia View personalizzata, in questo caso un oggetto
// di tipo UILabel
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section {
 
    UILabel *label = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
    label.font = [UIFont boldSystemFontOfSize:20];
    label.textAlignment = UITextAlignmentCenter;
    label.shadowColor = [UIColor blackColor];
    label.shadowOffset = CGSizeMake(1, 1);
    label.text = @"Sezione"; // Sostituire con un array come al solito
    label.textColor = [UIColor whiteColor];
    label.backgroundColor = [UIColor clearColor];
    label.opaque = NO;
 
    return label;
}
// Bisogna supportare anche questo message altrimenti non funziona
- (CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section {
   return 44;
}

È importante inserire anche heightForHeaderInSection, altrimenti non funziona.

Note interessanti

Nella creazione della nostra UILabel, che volendo potrebbe essere anche un oggetto più complesso come una UIView o UIImageView, ho utilizzato per inizializzare il frame CGRectZero che corrisponde a CGRectMake(0,0,0,0).

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...



Stop SOPA