IN QUESTO ARTICOLO MOSTRIAMO COME REALIZZARE UNA SVEGLIA DIGITALECHE CI AVVISERÀ DI IMPEGNI E SCADENZE IMMINENTI. SARÀ L’OCCASIONEDI APPROFONDIRE I CONCETTI LEGATI ALLA GESTIONE DELL’INTERFACCIA E DEL TIMER
In questo articolo mostreremo come realizzare una sveglia digitale. Grazie a questo progetto avremo modo di introdurre alcune classi di estrema utilità: NSTimer, fornita dal framework Foundation, che insieme a UIKit rappresenta le fondamenta di tutte le applicazioni per iPhone, e AVAudioPlayer, presente nel framework AVFoundation, il cui scopo è consentire l’esecuzione di brani audio di “qualunque” dimensione.
Per questo semploce esempio non useremo i delegate del multitasking quindi la sveglia funzionerà solo quando l’applicazione è in esecuzione (vedremo il multitasking in un prossimo tutorial).
IL TIPO DI PROGETTO
Per realizzare questo software utilizzeremo un nuovo tipo di progetto fornito da XCode chiama- to Utility Application: gli applicativi che vengono identificati con questo termine sono costituiti da due UIViewController contenenti una singola UIView ciascuno, che si alternano in base alla pressione di un preciso tasto. Il viewcontroller principale viene chiamato automaticamente MainViewController.Il passaggio dall’una a l’altra schermata avviene con la pressione del pulsante i nel MainView, e con l’utilizzo di quello con label done, posiziona- to in alto a sinistra nella barra di navigazione di FlipsideViewController.
IL COMPONENTE UIDATEPICKER
Inserendo un componente del tipo UIDatePicker all’interno della nostra interfaccia grafica, nel FlipsideViewController, forniremo all’utente la possibilità di selezionare una data, con una precisione a nostra discrezione; in questo caso impostiamo, tramite Interface Builder, il formato completo (giorno, mese, anno, ore, minuti) settando mode al valore “Date and Time”, la lingua italiana utilizzando il campo locale, e la precisione, con il campo interval, ad 1 minuto. UIDatePicker fornisce un metodo per ottenere la data selezionata, questa è un’istanza della classe NSDate e, quando torneremo al MainView provvederemo a memorizzarla in una cartella dell’iPhone, ed utilizzarla per verificare se l’allarme dovrà essere eseguito.
CONTROLLO NSTIMER
Un timer è un sistema che permette di cadenza- re l’esecuzione di un metodo con precisi inter- valli; ogni timer viene eseguito in un thread distinto.
[code lang=”obj-c”]NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1
target: self selector: @selector(handleTimer:) userInfo: nil repeats: YES];
– (void) handleTimer: (NSTimer *)
timer{
//metodo invocato da NSTimer
}[/code]
Con questo codice abbiamo realizzato un timer che viene avviato ogni secondo (o nei millesimi successivi), che allo scadere dell’intervallo ese gue il metodo handleTimer e che si ripete all’infi nito. Il metodo viene immediatamente avviato dopo la sua esecuzione e subisce un retain auto matico. Quando, (e se), non avremo più bisogno di questa istanza basterà invocare su di essa il metodo invalidate, che provvederà ad effettuare su di essa un release automatico. Per il nostro scopo questo metodo dovrà verificare se è giunto il momento per eseguire l’audio dell’allarme, operazione effettuabile semplicemente confrontando la data attuale, ottenuta richiedendo il valore del campo date dalla classe NSDate, con quella prelevata dall’UIDatePicker:timeIntervalSinceNow restituisce un valore positivo, i secondi mancanti alla data attuale, quando alarmDate è una data futura, mentre i valori sono negativi se alarmDate è ormai trascorso. Abbiamo dovuto utilizzare sia l’uguaglianza che il simbolo di minore uguale perché, come è stato detto, non si può prevedere se il timer verrà eseguito nel preciso minuto in cui dovrebbe scattare l’evento, o in uno dei successivi.
[code lang=”obj-c”]- (void) handleTimer: (NSTimer *)
timer{
if ([alarmDate timeIntervalSinceNow]<=0){
//esegue il suono dell’allarme
}
}[/code]
Dopo aver selezionato una data adoperando l’UIDatePicker, provvederemo a memorizzarla in una cartella locale all’iPhone e a caricarla ogni volta che il nostro applicativo verrà eseguito. All’interno del telefono esistono alcune cartelle liberamente accessibili e modificabili nelle quali potremo salvare qualunque tipo di informazione: tmp e Documents. La prima deve essere utilizzata per creare e gestire informazioni il cui tempo di vita è limitato alla singola esecuzione, mentre la seconda per tutti quei casi in cui un dato deve permanere per diversi avvii dell’applicativo. Esistono svariati metodi per ottenere la corretta posizione di queste cartelle, che sono uniche per ogni software, possiamo utilizzare il metodo del Core Data oppure possiamo usare le librerie fornite da .
AVAUDIOPLAYER
AVFramework, (Audio Video Foundation Framework), è un framework che consente di eseguire e anche registrare brani audio AVAudioPlayer è una delle classi fornite da tale libreria che consente l’esecuzione di un singolo file audio (uno per istanza); AVAudioPlayer consente di mettere in pausa e interrompere un audio, avere informazioni sulla sua durata e sulla posizione in cui è al momento l’esecuzione, consente infine di monitorare i vari livelli di volume assunti dall’audio. Questa classe accetta tutti i formati supportati dall’iPhone:
- AAC
- HE-AAC
- AMR (Adaptive Multi-Rate, a format for spee-ch)
- ALAC (Apple Lossless)
- iLBC (internet Low Bitrate Codec, another format for speech)
- IMA4 (IMA/ADPCM)
- linear PCM (uncompressed)
- μ-law and a-law
- MP3 (MPEG-1 audio layer 3
Nel nostro progetto utilizzeremo un loop audio, il tipico scandire del tempo di un orologio a tempo, e un suono che avviserà dell’allarme. Prima di effettuare qualunque operazione è necessario aggiungere AVFoundation.framework tra i framework (TUTORIAL) che utilizzerà il progetto e importarlo all’interno di MainViewController (
[code lang=”obj-c”]#import <AVFoundation/AV Foundation.h>[/code]
). Il codice per eseguire un file audio è relativamente breve: prima provvediamo a identificare il path completo della risorsa che ci interessa, (un file mp3 in questo caso), poi creeremo un’istanza di AVAudioPlayer, imposteremo il volume, il numero di esecuzioni e lo avvieremo:
[code lang=”obj-c”]NSString *path = [[NSBundle mainBundle] pathForResource:@"clock" ofType:@"mp3"];
AVAudioPlayer player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:nil];
player.volume = 0.4f;
[player prepareToPlay];
[player setNumberOfLoops:-1];
[player play];
[/code]
AVAudioPlayer ha un costruttore che accetta un URL, (che in questo caso sarà la posizione assunta nel nostro software dalla risorsa chiamata clock.mp3), e una variabile per memorizzare possibili errori (in questo progetto la abbiamo ignorata, impostandola a nil). Il campo volume è un float il cui intervallo è [0,1], dove con 0 si intende il silenzio, mentre con 1 il massimo valore consentito; il metoto prepareToPlay memorizza l’audio in un buffer prima di avviare l’esecuzione in modo da evitare interruzioni dovute al caching del file durante il play; setNumberOfLoops: può assumere un qualunque valore negativo per indicare un loop infinito, 0 per una singola esecuzione, i per (i+1) ripetizioni, inserendo 1 si avranno quindi due avvii successivi del suono. Se volessimo monitorare quando un suono è terminato basterà aggiungere il metodo audioPlayerDid FinishPlaying: all’interno della nostra classe, appartenente al protocollo AVAudioPlayerDelegate:
[code lang=”obj-c”]- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
//il suono è terminato
}[/code]
CONCLUSIONI
In questo articolo abbiamo introdotto numerosi argomenti interessanti che consentono di realizzare soluzioni anche molto complesse, giochi compresi granzie a NSTimer siamo in grado di far ripetere porzioni di codice in tempi prestabiliti.