Articoli con Tag ‘Apple iPhone’


10 utili snippet Objective-C

Spostare il doppio Tap sul simulatore

Il simulatore iPhone/iPad in Xcode permette di simulare il doppio tap con la pressione del tasto ALT. Questo è utile per simulare anche la funzione di Pinch, quella usata per ingrandire o allontare contenuti nelle view con scroll o in oggetti UIWebView. Ebbene, alcuni di voi avranno notato che la simulazione delle “due dita” procede in modo simmetrico partendo sempre dal centro dello schermo. Per muovere questo “centro” è sufficiente tenere premuto anche il tasto SHIFT.

Continua...

Very short snippet: detect iPad sul device e sul Web

Non sono solo i browser dei desktop o portatitli a navigare sui siti da noi realizzati, ormai l’era del mobile – del browser mobile – è diffusa, grazie a device come l’Apple iPhone, iPad, Android, etc… Inoltre, anche per chi sviluppa per Apple iPhone è diventato obbligatorio capire su quale device l’applicazione sta girando.

Sul Web la situazione è simile a quella esposta in Browser o Mobile Browser?, con la variante:

Continua...

Private API nella rimozione dello scroll in un oggetto UIWebView

In Very short snippet: rimuovere lo scroll da un oggetto UIWebView avevamo visto come era possibile rimuovere lo scroll da un oggetto UIWebView:

Continua...

Objective-C: ottenere informazioni a partire da Latitudine e Longitudine

Rispondo a Mirko che mi chiedeva come realizzare il caso inverso proposto in Come ottenere Latitudine e Longitudine in Objective-C.
Partendo dai valori di Latitudine e Longitudine è possibile sfruttare la classe MKReverseGeocoder per ottenere tutta una serie di informazioni, come: la città, lo stato, l’indirizzo esteso, il cap!

Continua...

Very short snippet: rimuovere lo scroll da un oggetto UIWebView

Documentata, o non documentata, una funzionalità, a volte, la si è costretti ad implementare per forza! Utile, in alcune situazione, è rimuovere lo scroll da un oggetto UIWebView. È interessante, in generale, notare come è possibile accedere ai componenti “interni” facenti parte dell’oggetto in questione: in questo esempio si recupera il puntatore all’oggetto UIScrollView presente nell’oggetto UIWebView:

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

iPhone: eliminare l’effetto ombra durante lo scroll in un UIWebView

In questo ultimo periodo ho lavorato su tre applicazioni per Apple iPhone, praticamente in contemporanea. Due sono state già approvate da Apple e si trovano su App Store: TheFirst e iMakeLove.

TheFirst iMakeLove

In entrambe le applicazioni ho adottato l’uso di un oggetto UIWebView per visualizzare le istruzioni.
L’oggetto UIWebView si è ilevato davvero comodo in questo caso. Mi ha permesso di visualizzare in modo rapido e gradevole una testo, corredandolo in caso di immagini e qualsiasi altra cosa sia visualizzabile su una pagina Web (Flash escluso su iPhone).

TheFirst

L’oggetto UIWebView è davvero versatile e necessita di pochissime impostazioni per essere utilizzato. Unico difetto riscontrato è la presenza di una misteriosa ombra che appare quando si effettua uno scroll fuori dall’area del controllo, sia in basso che in alto:

UIWebView Shadow

Dopo varie ricerche ho capito che questo comportamento dipende dalle SDK, in particolare dagli ultimi aggiornamenti. Inoltre Apple non ha rilasciato nessuna dichiarazione ufficiale su come rimuoverlo, al contrario ha bollato come codice non permesso una serie di hack che fanno uso di funzioni riservate o non documentante. Alla fine avevo lasciato perdere, sia per questioni di tempo, sia perchè le soluzioni sembravano tutte fuori dagli schemi Apple.
Fortunatamente mi è arrivata la soluzione, spero abbastanza regolare, che sembra proprio risolvere il problema (grazie ad Adolfo):

1
2
3
4
5
6
// webView è il controllo UIWebView
id scroller = [webView.subviews objectAtIndex:0];

for (UIView *subView in [scroller subviews])
    if ([[[subView class] description] isEqualToString:@"UIImageView"])
        subView.hidden = YES;

Come sottolineato da Adolfo questo è comunque un hack che potrebbe smettere di funzionare con futuri rilasci delle SDK.

Continua...

Objective-C: esporre proprietà in una classe

Vorrei mostrare e discutere alcuni esempi sul come aggiungere e manipolare proprietà in una Classe Objective-C. Un esempio classico, per l’appunto, è il seguente; nella definizione della nostra interfaccia di classe definiamo due proprietà nome e cognome:

1
2
3
4
5
6
7
8
9
10
11
// MyClass.h
#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    NSString *nome;
    NSString *cognome;
}

@property (retain) NSString *nome;
@property (retain) NSString *cognome;
@end

Nel file di implementazione inseriamo la dichiarazione @synthesize in modo tale che Xcode produca per noi i metodi getter e setter usati rispettivamente per leggere ed impostare le nostre due proprietà:

1
2
3
4
5
6
7
8
// MyClass.m
#import "MyClass.h"

@implementation MyClass

@synthesize nome, cognome;

@end

Quando andremo ad utilizzare la nostra classe MyClass, cioè quando istanziaremo un oggetto di tipo MyClass, possiamo scrive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// qualsiasi altra classe, come AppDelegate
// nel file .h
#import <UIKit/UIKit.h>
#import "MyClass.h"

@class TestViewController;

@interface TesAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    TestViewController *viewController;

    MyClass *miaClasse;
}

// nel file .m
miaClasse = [MyClass alloc];
miaClasse.nome = @"Giovambattista";
NSLog(@"miaClasse.nome = %@", miaClasse.nome);

Oppure, che è equivalente:

1
2
3
// sempre nel file .m
[miaClasse setNome:@"Undolog"];
NSLog(@"miaClasse.nome = %@",[miaClasse nome]);

Fin qui tutto bene. Tuttavia potrebbe fuorviare l’equivalenza delle “variabli” interne (ivar) con il nome della proprietà vera e propria. Per capire la differenza, ripropongo lo stesso esempio facendo a meno, questa volta, di @synthesize. Ora, quindi, dovremmo occuparci noi di scrivere i metodi getter e setter. Per sottolineare ulteriormente le differenze, rinominerò le variabili interne inserendo un underscore davanti al nome. Ma vediamo il codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    NSString *_nome;
    NSString *_cognome;
}

- (NSString *) nome;                               // get
- (NSString *) cognome;                            // get

- (void) setNome: (NSString *)stringaIngresso;     // set
- (void) setCognome: (NSString *)stringaIngresso;  // set

@end

A differenza dell’esempio precedente i puntatori alla variabili interne (incapsultate) sono diventati _nome e _cognome. Inoltre troviamo quattro definizioni di metodi che rappresentano le nostre get e set. @property è scomparso, in quanto non serve più.
Vediamo il file di implementazione MyClass.m:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import "MyClass.h"

@implementation MyClass

// get per "nome"
- (NSString *) nome {
    return _nome;
}
// set per "nome"
- (void) setNome: (NSString *)stringaIngresso {
    _nome = stringaIngresso;
}

// get per "cognome"
- (NSString *) cognome {
    return _cognome;
}
// set per "cognome"
- (void) setCognome: (NSString *)stringaIngresso {
    _cognome = stringaIngresso;
}

@end

Una classe così scritta potrà essere utilizzata esattamente come la precedente, cioè:

1
2
3
4
5
6
7
8
miaClasse = [MyClass alloc];
miaClasse.nome = @"Giovambattista";
NSLog(@"miaClasse.nome = %@", miaClasse.nome);

// Oppure, che è equivalente:

[miaClasse setNome:@"Undolog"];
NSLog(@"miaClasse.nome = %@",[miaClasse nome]);

A livello didattico l’abbandono di @synthesize ci ha costretto a scrivere “da soli” i metodi di get e set, evidenziando – anche con l’aggiunta dell’underscore – le differenze tra il nome della proprietà e la sua ivar interna _nome.
A livello funzionale l’uso dei metodi personali get e set permette un reale controllo del dato prima della sua impostazione (o prima della sua lettura) e quindi un reale incapsulamento per proteggere la variabile interna.
Ad esempio sarebbe possibile impedire il passaggio di stringhe vuote alla proprietà nome:

1
2
3
4
- (void) setNome: (NSString *)stringaIngresso {
    if( stringaIngresso == @"" ) stringaIngresso = @"senza nome";
    _nome = stringaIngresso;
}

Ulteriore variante

Se desiderate utilizzare le variabili interne con l’underscore davanti (chi rpoviene da Adobe Actionscript potrebbe essere abituato così) non è necessario abbandonare l’uso della direttiva @synthesize. Xcode permette infatti di “fondere” i metodi sopra indicati:

1
2
@synthesize nome = _nome;
@synthesize cognome = _cognome;

Così facendo potremmo usare internamente il puntatore a _nome, “sintetizzato” – verso l’esterno – come proprietà nome. Inoltre, se è vero che l’uso di @synthesize produce la generazione automatica dei metodi (messaggi) di getter e setter, è vero anche che lo fa solo se non li trova, quindi se desiderate “implementare” un vostro metodo di getter e/o setter potete farlo anche se avete usato la direttiva @synthesize.

Allocazioni di memoria

Negli esempi di sopra ho omesso alcuni dettagli importanti ai fini di una reale implementazione. Prima di tutto non ho illustrato nessun metodo init(), utile ai fini dell’inizializzazione dell’oggetto e dei sui valori di default. Inoltre, manca l’aggiunta di un metodo dealloc():

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
// file MyClass.m
#import "MyClass.h"

@implementation MyClass

- (id) init {
    if ( self = [super init] ) {
        _nome = @"Nome preimpostato";
        _cognome = @"Cognome preimpostato";
    }
    return self;
}

- (void) dealloc {
    [_nome release];
    [_cognome release];
    [super dealloc];
}

- (NSString *) nome {
    return _nome;
}
- (void) setNome: (NSString *)stringaIngresso {
    if( stringaIngresso == @"" ) stringaIngresso = @"senza nome";
    _nome = stringaIngresso;
}

- (NSString *) cognome {
    return _cognome;
}
- (void) setCognome: (NSString *)stringaIngresso {
    _cognome = stringaIngresso;
}

@end

In futuro vedremo poi i dettagli sulle proprietà readonly, retain, etc… :)

Continua...

Browser o Mobile Browser?

Il nostro sito Web ormai non è visualizzato solo da postazioni PC. Con la diffusione del mobile, grazie soprattutto ad Apple iPhone, l’accesso al sito o blog viene sempre più spesso effettuato da dispositivi mobili di vario tipo. Diventa quindi esigenza di molti Web Developer saper intercettare ed identificare i diversi “agenti”, cioè gli strumenti con cui un utente visualizza (naviga) le nostre pagine.

Continua...



Stop SOPA