• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

T#077 – Sfruttiamo Magnetometro e CoreGraphics nelle nostre applicazioni iPhone

By uncool | on 20 Ottobre 2010 | 27 Comments
Senza categoria

t077-Sfruttiamo-Magnetometro-QuartzCore-applicazioni-iPhone-00 Con questo tutorial voglio spiegare come ruotare dinamicamente un’immagine sfruttando un metodo presente in QuartzCore. Per tale dinamismo sfrutteremo inoltre il magnetometro, che ci permetterà di ruotare l’immagine nella direzione di marcia del nostro dispositivo (useremo per questo fine una figura a forma di freccia).

Partiamo con il nostro progetto

Apriamo Xcode e creiamo un nuovo progetto. Dall’elenco dei template disponibili selezioniamo “View-Based Application”. Proseguiamo e chiamiamo il nostro programmino “Rotation”.


t077-Sfruttiamo-Magnetometro-QuartzCore-applicazioni-iPhone-01

Aggiungiamo quindi un’immagine che rappresenti una freccia nel nostro progetto, se non ne avete una potete cercarla su google o eventualmente usare quella che abbiamo usato noi nel nostro esempio (che trovare riportata qui sotto). Includiamola quindi nel nostro progetto semplicemente trascinandola e facendo attenzione a spuntare “Copy items into destination group’s folder (if needed)”, che effettuerà di fatto una copia e non un semplice link a tale file.



Aggiungiamo i framework necessari

Facciamo tasto destro sulla cartella Frameworks -> Add -> Existing Frameworks e selezioniamo “QuartzCore” e “CoreLocation”


t077-Sfruttiamo-Magnetometro-QuartzCore-applicazioni-iPhone-02


t077-Sfruttiamo-Magnetometro-QuartzCore-applicazioni-iPhone-03

Apriamo quindi il nostro header “rotationViewController.h” e aggiungiamo le seguenti righe di codice:

#import 

Dichiariamo variabili di istanza e metodi

Sempre in questo file (rotationViewController.h) dobbiamo definire il protocollo di accesso al Magnetometro, che possiamo fare in questo modo:

@interface rotationViewController : UIViewController   {

Aggiungiamo quindi questi due oggetti e le relative property:

	
CLLocationManager	*locManager;
UIImageView		*imageRotation;
UILabel			*courseValue;
}

@property (assign, nonatomic) CLLocationManager *locManager;
@property (retain, nonatomic) IBOutlet UIImageView *imageRotation;
@property (retain, nonatomic) IBOutlet UILabel *courseValue;

“locManager” sarà l’oggetto che istanzieremo per accedere al GPS (nel nostro caso specifico il magnetometro), “imageRotation” è una semplice ImageView che conterrà la nostra immagine da ruotare dinamicamente, “courseValue” è una UILabel che conterrà il valore numerico graficato dalla nostra immagine.

Implementiamo il codice

Ok, ora possiamo spostarci sul nostro file di implementazione per scrivere il codice necessario all’accesso al magnetometro e alla successiva rotazione dell’immagine.

Usiamo la direttiva @syntesize per poter avere a disposizione i setter/getter delle variabili/oggetti definiti nell’header:

@synthesize locManager;
@synthesize imageRotation;
@synthesize courseValue;

Aggiungiamo quindi nel metodo “viewDidLoad” il seguente codice:

[imageRotation setImage:[UIImage imageNamed:@"arrow.png"]];
self.locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
[locManager startUpdatingHeading];

Con la prima istruzione assegnerò ad “imageRotation” (al momento del caricamento della vista) l’immagine precedentemente importata nel progetto, nel nostro caso l’immagine si chiama arrow.png.
Le tre righe successive istanziano l’oggetto “CLLocationManager” necessario per accedere alle proprietà del GPS/Magnetometro e deleghiamo se stesso come “ricevente” di tutti i messaggi generati da “LLocationManager”. Facciamo partire infine gli aggiornamenti generati dal magnetometro.
Nel nostro caso specifico andremo a leggere la sua proprietà “trueHeading“, un valore numerico che va da 0 a 359, che possiamo sommariamente considerare come:

  • valori tra 0 e 44 = Nord
  • valori tra 45 e 89 = NordEst
  • valori tra 90 e 134 = Est
  • valori tra 135 and 179 = SudEst
  • valori tra 180 and 234 = Sud
  • valori tra 235 and 269 = SudOvest
  • valori tra 270 and 314 = ovest
  • valori tra 315 and 359 = NordOvest

Andiamo a scrivere ora il metodo che “CLLocationManager” ci mette a disposizione per acquisire tale valore.

#pragma mark -
#pragma mark locManager Methods

 - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
	//acquisico il valore numerico indicante la mia "direzione"
	NSString *headValue = [[NSString alloc] initWithFormat:@"%3.0f", newHeading.trueHeading];
	//lo converto in intero
	int myIntHead = [headValue intValue];
	//lo faccio processare al metodo messo a disposizione da quartz facendo ruotare l'immagine
	//in base al radiante
	[imageRotation setTransform:CGAffineTransformMakeRotation(myIntHead * 3.14159/180)];
        courseValue.text = headValue;
	[headValue release];
}

“headValue” acquisirà un valore float composto da tre numeri interi restituito dalla proprietà “trueHeading” del Magnetometro. Con [headValute intValue] convertiremo il valore di headValue in intero.
La terza riga è quella che si occupa di rotare l’immagine e vuole come argomento un radiante. Tale radiante lo otteniamo semplicemente moltiplicando il valore di “trueHeading” per π/2.

Nella quarta riga printiamo sul display il valore che stiamo graficando tramite la freccia.

Gestiamo la memoria

Come buona norma per la gestione della memoria rilasciamo tutto quello che abbiamo allocato:

- (void)viewDidUnload {
	[locManager stopUpdatingHeading];
	self.locManager = nil;
	self.imageRotation = nil;
}
- (void)dealloc {
    [super dealloc];
	[locManager release];
	[imageRotation release];
}

Disegnamo la semplice interfaccia grafica della nostra applicazione

Salviamo il lavoro svolto fino ad ora ed apriamo il file “rotationViewController.xib” in InterfaceBuilder (tramite semplice doppio-clik sullo stesso).

Qui dentro dobbiamo aggiungere una ImageView e due Label, una contenente un identificativo ed una connessa ad courseValue.
Ridimensioniamola e colleghiamola a “imageRotation” che abbiamo definito precedentemente all’interno del nostro codice.


t077-Sfruttiamo-Magnetometro-QuartzCore-applicazioni-iPhone-04

Salviamo e proviamo finalmente il nostro progetto.

ATTENZIONE: occorrerà provare direttamente su un device, altrimenti non noteremo alcuna differenza.

Se avete problemi con il tutorial, questo è il nostro file di progetto.



Share this story:
  • tweet

Tags: animazionibussola iPhone sdkCoreGraphicsCoreLocationmagnetometroQuartzCoreTutorial Pratici

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • T#078 – Creiamo una subView personalizzata da codice (Xcode e Objective-C)

    29 Ottobre 2010 - 5 Comments
  • T#029 – Muoviamo una pallina tramite l’accelerometro

    1 Aprile 2010 - 43 Comments
  • UINavigationController – Guida completa all’uso

    21 Marzo 2010 - 19 Comments

Author Description

27 Responses to “T#077 – Sfruttiamo Magnetometro e CoreGraphics nelle nostre applicazioni iPhone”

  1. 20 Ottobre 2010

    Tweets that mention Sfruttiamo Magnetometro e QuartzCore nelle nostre applicazioni iPhone | devAPP -- Topsy.com

    […] This post was mentioned on Twitter by Fast-Devs Project, Bubi Devs. Bubi Devs said: T#077 – Sfruttiamo Magnetometro e CoreGraphics nelle nostre applicazioni iPhone: Con questo tutorial voglio spiega… http://bit.ly/a0kr00 […]

  2. 20 Ottobre 2010

    daniele

    Bel tutorial!! peccato non poterlo usare sul mio iphone2g.

  3. 20 Ottobre 2010

    uncool

    ciao daniele, per fare un test con CGAffineTransformMakeRotation si puo’ scrivere un generatore di numeri casuali temporizzato che ruota randomicamente una immagine con tale funzione, dopo o al piu tardi domani lo integro con questa possibilità.
    Per chi non ha un magnetometro ma il gps puo’ prendere la proprietà course di CLLocationManager

  4. 20 Ottobre 2010

    fast

    salve, c’è un problema: l’immagine non viene visualizzata sull’iphone xk il nome dell’immagine nel progetto è diversa da quello reale….poi per far andare la figura a nord il valore @%0.1f va bene??

  5. 20 Ottobre 2010

    uncool

    Ciao, riguardo che cosa c’è linkato nel progetto come immagine.
    Non capisco la seconda domanda: cosa intendi per far andare la figura a nord? Quello lo devi calcolare in quanto trueHeading si riferisce alla “direzione di marcia” dell’iphone

  6. 20 Ottobre 2010

    Fast

    Nel senso che la rosa gira al contrario…solo tenendo l’iPhone a faccia in giu gira in maniera corretta…probabilmente qualche calcolo sbagliato…come si aggiusta??

  7. 20 Ottobre 2010

    uncool

    la freccia non indica il nord, indica l’orientamento dell’iphone rilevato tramite il magnetometro.
    Se per esempio stai camminando con il dispositivo in mano e la freccia indica il basso vuol dire che tu (device) ti stai muovendo verso sud.
    Puoi far printare a video il valore di headValue in una label.
    Ora faccio una modifica al progetto aggiungendo questa parte ed integro le parti di codice modificate

  8. 21 Ottobre 2010

    uncool

    post e codice di esempio aggiornato

  9. 22 Ottobre 2010

    marco

    con il mio iPhone 3g non funziona è normale?

  10. 22 Ottobre 2010

    uncool

    Ciao Marco si è normale, in quanto il 3g non ha integrato il magnetometro.
    Si puo’ fare la stessa cosa sul 3g prendendo il proprieta’
    course
    di CLLocationManager senza usare il metodo

    – (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading

  11. 14 Febbraio 2011

    Ragazzetto

    Una domanda :
    qualcuno mi sa dire come mai non va su ipad ?
    è un problema del mio iPad o c’ è qualcosaltro ?

    P.S. : sicuramente la cosa aiuterebbe molto anche fast !

  12. 14 Febbraio 2011

    Ragazzetto

    non sarà mica un bug della beta del 4.3 ?
    in ogni caso le altre app che hanno portato la bussola sull ipad funzionano !
    strano……. molto strano !

  13. 4 Aprile 2011

    fast


    Ragazzetto:

    non sarà mica un bug della beta del 4.3 ?
    in ogni caso le altre app che hanno portato la bussola sull ipad funzionano !
    strano……. molto strano !

    si, infatti aiuterebbe molto sapere xk su ipad non va e come fare la stessa cosa su iphone 3g e magari sapere come fare per indicare anche la direzione della freccia (es.: NO, N, ecc.)

  14. 4 Aprile 2011

    giorgio

    Ciao, su ipad non ho modo di testarlo, per il 3g quindi senza magnetometro puoi prendere come riferimento i valori delle macrocoordinate (N – NE – E – …) indicati nel primo post e nella

    – (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation {

    puoi fare una cosa del genere

    NSString *courseString = [[NSString alloc] initWithFormat:@”%3.0f”, newLocation.course];
    NSString *oldCourseString = [[NSString alloc] initWithFormat:@”%3.0f”, oldLocation.course];
    int myLastCourse = [oldCourseString intValue];
    int myIntCourse = [courseString intValue];
    oldCourse = myLastCourse;
    if (myIntCourse =0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(oldCourse * 3.14159/180)];
    }
    if (myIntCourse >= 0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(myIntCourse * 3.14159/180)];
    }
    [courseString release];
    [oldCourseString release];

  15. 4 Aprile 2011

    giorgio

    ovviamente questo codice lo fai eseguire controllando con una BOOL la presenza o meno del magnetometro con una cosa del genere

    BOOL magne;

    if (locManager.headingAvailable) {
    [locManager startUpdatingHeading];
    magne = YES;
    } else {
    magne = NO;
    }

  16. 4 Aprile 2011

    fast


    giorgio:

    ovviamente questo codice lo fai eseguire controllando con una BOOL la presenza o meno del magnetometro con una cosa del genere
    BOOL magne;
    if (locManager.headingAvailable) {
    [locManager startUpdatingHeading];
    magne = YES;
    } else {
    magne = NO;
    }

    mmmm….nn so se ho capito bn ma provo

  17. 5 Aprile 2011

    giorgio

    chiedi pure se non ti è chiaro qualcosa che cerco di metterlo giu meglio.

  18. 5 Aprile 2011

    giorgio


    giorgio:

    Ciao, su ipad non ho modo di testarlo, per il 3g quindi senza magnetometro puoi prendere come riferimento i valori delle macrocoordinate (N – NE – E – …) indicati nel primo post e nella
    – (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation {
    NSString *courseString = [[NSString alloc] initWithFormat:@”%3.0f”, newLocation.course];
    NSString *oldCourseString = [[NSString alloc] initWithFormat:@”%3.0f”, oldLocation.course];

    ovviamente course è una proprieta di CLLocationManager, per ottenerla il gps deve acquisire correttamente almeno 3 dati validi (l’invalid su questa proprietà è -1) per cui per iphone 3g tale meccanismo è testabile solo all’aperto e dopo che avrà acquisito almeno 3 dati validi

  19. 5 Aprile 2011

    fast


    giorgio:


    giorgio:

    Ciao, su ipad non ho modo di testarlo, per il 3g quindi senza magnetometro puoi prendere come riferimento i valori delle macrocoordinate (N – NE – E – …) indicati nel primo post e nella
    – (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation {
    NSString *courseString = [[NSString alloc] initWithFormat:@”%3.0f”, newLocation.course];
    NSString *oldCourseString = [[NSString alloc] initWithFormat:@”%3.0f”, oldLocation.course];

    ovviamente course è una proprieta di CLLocationManager, per ottenerla il gps deve acquisire correttamente almeno 3 dati validi (l’invalid su questa proprietà è -1) per cui per iphone 3g tale meccanismo è testabile solo all’aperto e dopo che avrà acquisito almeno 3 dati validi

    nn sarebbe meglio aggiornare questo articolo in modo che funzioni sia su iphone 3g che su iphone 4

  20. 5 Aprile 2011

    fast

    oh almeno il source code

  21. 5 Aprile 2011

    giorgio

    Aggiornero’ source code per farlo andare su 3g (ovviamente sul4 le chiamate sono le stesse e l’attuale funziona) ma appunto non si tratta piu di sfruttare il magnetometro ma si utilizzano proprietà di un oggetto differente.
    Postero’ qui una volta aggiornato il codice.

  22. 5 Aprile 2011

    fast


    giorgio:

    Aggiornero’ source code per farlo andare su 3g (ovviamente sul4 le chiamate sono le stesse e l’attuale funziona) ma appunto non si tratta piu di sfruttare il magnetometro ma si utilizzano proprietà di un oggetto differente.
    Postero’ qui una volta aggiornato il codice.

    Ok, però nn si può fare come un “if” che se è su iphone 3g usa un metodo e su 4 un’altro (in modo da usare il magnetometro sul 4 e il gps sul 3)?

  23. 5 Aprile 2011

    giorgio

    come ti ho scritto prima, setti una variabile di tipo bool

    BOOL magne;

    nella viewDidLoad metti questo if

    //iniziamo a collezionare i dati gps
    [locManager startUpdatingLocation];

    if (locManager.headingAvailable) {
    [locManager startUpdatingHeading];
    magne = YES;
    } else {
    magne = NO;
    }

    se magne = YES siamo nel caso di iphone 3g, e quindi andiamo ad implementare il metodo
    – (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation {

    tale metodo sarà chiamato (in parole povere) ogni qualvolta ci saranno delle coordinate nuove.
    all’interno di questo metodo aggiungi:

    NSString *courseString = [[NSString alloc] initWithFormat:@”%3.0f”, newLocation.course];
    NSString *oldCourseString = [[NSString alloc] initWithFormat:@”%3.0f”, oldLocation.course];
    int myLastCourse = [oldCourseString intValue];
    int myIntCourse = [courseString intValue];
    oldCourse = myLastCourse;
    if (myIntCourse =0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(oldCourse * 3.14159/180)];
    }
    if (myIntCourse >= 0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(myIntCourse * 3.14159/180)];
    }
    [courseString release];
    [oldCourseString release];

    è chiaro ed è gia’ stato spiegato all’inizio dell’articolo.

    In caso di iphone 3gs/4 il codice rimane invariato, basta implementare il seguente metodo / codice

    – (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
    {
    //acquisico il valore numerico indicante la mia “direzione”
    NSString *headValue = [[NSString alloc] initWithFormat:@”%3.0f”, newHeading.trueHeading];
    //lo converto in intero
    int myIntHead = [headValue intValue];
    //lo faccio processare al metodo messo a disposizione da quartz facendo ruotare l’immagine
    //in base al radiante
    [imageRotation setTransform:CGAffineTransformMakeRotation(myIntHead * 3.14159/180)];
    courseValue.text = headValue;
    [headValue release];
    }

    Domani vedo di aggiornare il sorgente.

  24. 6 Aprile 2011

    fast


    giorgio:

    come ti ho scritto prima, setti una variabile di tipo bool
    BOOL magne;
    nella viewDidLoad metti questo if
    //iniziamo a collezionare i dati gps
    [locManager startUpdatingLocation];
    if (locManager.headingAvailable) {
    [locManager startUpdatingHeading];
    magne = YES;
    } else {
    magne = NO;
    }
    se magne = YES siamo nel caso di iphone 3g, e quindi andiamo ad implementare il metodo
    – (void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation {
    tale metodo sarà chiamato (in parole povere) ogni qualvolta ci saranno delle coordinate nuove.
    all’interno di questo metodo aggiungi:
    NSString *courseString = [[NSString alloc] initWithFormat:@”%3.0f”, newLocation.course];
    NSString *oldCourseString = [[NSString alloc] initWithFormat:@”%3.0f”, oldLocation.course];
    int myLastCourse = [oldCourseString intValue];
    int myIntCourse = [courseString intValue];
    oldCourse = myLastCourse;
    if (myIntCourse =0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(oldCourse * 3.14159/180)];
    }
    if (myIntCourse >= 0) {
    [dir setImage:[UIImage imageNamed:@”no.png”]];
    [dir setTransform:CGAffineTransformMakeRotation(myIntCourse * 3.14159/180)];
    }
    [courseString release];
    [oldCourseString release];
    è chiaro ed è gia’ stato spiegato all’inizio dell’articolo.
    In caso di iphone 3gs/4 il codice rimane invariato, basta implementare il seguente metodo / codice
    – (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
    {
    //acquisico il valore numerico indicante la mia “direzione”
    NSString *headValue = [[NSString alloc] initWithFormat:@”%3.0f”, newHeading.trueHeading];
    //lo converto in intero
    int myIntHead = [headValue intValue];
    //lo faccio processare al metodo messo a disposizione da quartz facendo ruotare l’immagine
    //in base al radiante
    [imageRotation setTransform:CGAffineTransformMakeRotation(myIntHead * 3.14159/180)];
    courseValue.text = headValue;
    [headValue release];
    }
    Domani vedo di aggiornare il sorgente.

    ok grazie

  25. 10 Maggio 2011

    fast

    va bhè..

  26. 15 Giugno 2011

    Fra

    Scusate, mi servirebbe un’informazione urgente. Sto cercando di creare una variabile CLLocation da valori di latitudine e longitudine LONG INT. Come faccio?

  27. 10 Luglio 2012

    nicolas

    ciao a tutti volevo chiedervi: quando lancio l’applicazione (con i servizi di localizzazione spenti) la bussola non si muove. se li accendo va tutto alla perfezione. volevo chieedere è possibile far ruotare la bussola senza il gps attivo, visto che molte app lo fanno? grazie

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO