Programming iOS lezione 2
Upcoming SlideShare
Loading in...5
×
 

Programming iOS lezione 2

on

  • 2,495 views

 

Statistics

Views

Total Views
2,495
Views on SlideShare
1,969
Embed Views
526

Actions

Likes
0
Downloads
36
Comments
0

8 Embeds 526

http://alitalia.noblogs.org 501
http://www.jugsardegna.org 17
http://www.linkedin.com 3
http://www.slideshare.net 1
http://jugsardegna.org 1
http://www.jugsardegna.org:8080 1
http://webcache.googleusercontent.com 1
http://131.253.14.98 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Programming iOS lezione 2 Programming iOS lezione 2 Presentation Transcript

  • LE TABLE VIEW
  • Cosa sono le Table View?Le table view sono gli elementi più comuniQuasi tutte le applicazioni di base di iPhone le usanoRendono facile la visualizzazione delle informazioniPossono essere di due tipi differenti: Plain Grouped
  • DettagliUna tabella è costituita da tre elementi: Una view Un’origine dati Un delegatoIniziamo dalla primaUna UITableView è una classe che presenta una tabella a video
  • Origine dati per una table viewUn’origine dati è un oggetto che descrive la relazione traUITableView e il suo contenutoGran parte delle funzioni sono svolte dal protocolloUITableViewDataSourceDispone di metodi per gestire l’inserimento, l’eliminazione el’ordinamento di righe nella tabellaI metodi richiesti sono tableView:numberOfRowsInSection: eTableView:cellForRowAtIndexPath:
  • DelegatoConsente all’applicazione host di avere maggior controllosull’aspetto e il comportamento della casellaRiceve notifiche per le varie azioni dell’utenteAltri metodi consentono al delegato di fornire viewpersonalizzate
  • Navighiamo nella tabellaCreiamo un nuovo progetto con Navigation Based ApplicationApriamo File->new Project in XcodeNon selezionare Use Core Data for StorageAssegnate al progetto MovieTable come nomeOra apriamo MainWindow.xib in IB e passiamo alla view adelencoIl progetto ha un navigation controller con una navigation bar
  • Dove si trova la tabella?Aprite RootViewController.xib, e vedrete il contenuto comesingolo oggetto UITableViewVediamo come dataSource e delegate sono connessi al F’sOPer tornare alla precedente astrazione vediamo come: RootViewController fa da delegato e origine dati La classe fornisce i metodi minimi per eseguire l’applicazione
  • Nota mnemonicaTenete sempre presente una cosa quando avete a che fare conTablesÈ SEMPRE necessario implementare le seguenti interfacce: UITableViewDataSource UITableViewDelgateRigorosamente da aggiungere all’@interface
  • Sviluppiamo il modello MVCPer il modello prendiamo la classe Movie della lezione primaIn group and files fare Ctrl+Click sulla classe e scegliere Add->Existing FilesNavigare fino al precedente progetto Movie e importare i duefiles .h e .mAssicurarsi di selezionare Copy Items into destination..
  • Modifiche al codice Aggiungete #import<Movie.h> al RootViewController.h Dichiarate la variabile istanza NSMutableArray moviesArray; Decommentiamo il metodo viewDidLoad in RootViewController.m e aggiungere il codice- (void)viewDidLoad { [super viewDidLoad]; moviesArray = [[NSMutableArray alloc] init]; Movie *aMovie = [[Movie alloc] init];! aMovie.title = @"Plaything Anecdote";! aMovie.boxOfficeGross = [NSNumber numberWithInt: 191796233];! aMovie.summary =! @"Did you ever think your dolls were really alive? Well, they are.";! [moviesArray addObject: aMovie];! [aMovie release];
  • Aggiornamento Aggiorniamo i nostri metodi per restituire la lunghezza dell’array- (NSInteger)tableView:(UITableView *)tableView! ! ! numberOfRowsInSection:(NSInteger)section {! return [moviesArray count];} Il codice precedente mostra che la tabella ha una sola riga Al momento dell’esecuzione verrà richiamato il metodo TableView:cellForRowAtIndexPath: Si otterrà quindi una UITableView per tale riga Per personalizzare la cella inserire il codice dopo il commento
  • NSIndexPathPerché usiamo NSIndexPath?È un oggetto che specifica un percorso attraverso una strutturaad alberoParte da un insieme di numeri interi che iniziano da zeroSu iPhone OS questa classe è estesa con proprietà specificheLa sezione e la riga son indicate come indexPath.{section,row}
  • Aggiunta del codice Quindi nel metodo di TableView:cellForRowAtIndexPath: aggiungeremo:Movie *aMovie = [moviesArray objectAtIndex:indexPath.row];cell.textLabel.text = aMovie.title;cell.detailTextLabel.text = aMovie.summary; La prima riga contiene il membro di moviesArray Nella seconda e terza presentiamo titolo e dettaglio del film
  • Proprietà della cellaLa cella di default ha tre proprietà principali textLabel detailTextLabel imageViewPer usare detailTextLabel dobbiamo usare uno stile differentedi cella
  • Stili di CellaEsistono quattro stili di cella differenti UITableViewCellStyleDefault (Testo con allineamento a Sx) UITableViewCellStyleSubtitle (Seconda riga con dettagli) UITableViewCellStyleValue1 (Dettagli a destra) UITableViewCellStyleValue2 (testo blu a Dx e dettagli a dx)
  • Riutilizzo delle celleNel metodo che stiamo utilizzando cellForRowAtIndexPath:esiste: l’inizializzatore per UITableViewCell: richiede la stringa: CellIdentifier: serve per recuperare la cella nel caso di scomparsa dallo schermo È una cache per il contenuto che non viene ricaricato Si reimposta il contenuto invece di creare nuove celle
  • Aggiungere la rimozioneÈ semplice e veloce scegliere dara la possibilità di rimuoverecelleBasta decommentare la funzionetableView:canEditRowAtIndexPath:Basta cambiare il valore di ritorno su YESPer la rimozione vera e propria invece è necessario utilizzaretableView:commitEditingStyle:forRowAtIndexPath:
  • Scriviamo il codiceCome al solito è tutto già implementatoDobbiamo solo supportare un pezzo di codiceIn questo caso UITableViewCellEditingStyleDeleteUI TableView fornisce già il metododeleteRowsAtIndexPaths:withRowsAnimation:Per il modello c’è removeObjectAtIndex:
  • Codice, codice, codice... - (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source. [moviesArray removeObjectAtIndex: indexPath.row]; [tableView deleteRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } }In questo modo otteniamo il classico comportamento trascinaper eliminareOra impostiamo anche il bottone di edit Decommentiamoself.navigationItem.leftBarButtonItem =self.editButtonItem; in ViewDidLoad:
  • Navigar m’è dolce..Nel capitolo precedente abbiamo usato una view modaleL’abbiamo presentata col metodo presentModalViewController:Ora la navigazione è gestita da UINavigationControllerDobbiamo prendere la classe MovieEditorViewControllerCopiamo le due classi e il file xib con la solita tecnicaSpostiamo lo xib nel gruppo Resources
  • Alcune ModificheVisto che precedentemente occupava tutto lo schermoOra la view va modificata con Simulated Interface Elements in IBImpostare Top Bar a Navigation BarCreiamo un IBOutlet in RootViewControllerAggiungiamo MovieEditorViewController *movieEditor; .... la property associata IBOutlet MEVC *movieEditor;
  • DettagliFacciamo @synthesize per questa proprietà nel file .mInseriamo #import "MovieEditorViewController.h" nell’headerCreiamone un’istanza in IBTrasciniamo UViewController dalla Lib in RootViewControllerCome identity impostiamo MovieEditorViewControllerConnettiamo movieEditor all’oggetto view controller
  • Modifica di un elemento tableView:DidSelectRowAtIndexPath: fornisce un template Questo crea una nuova view A noi non serve, useremo quella già fatta Modificheremo la classe nel seguente modo:- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Navigation logic may go here -- for example, create and push another view controller.! // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];! // [self.navigationController pushViewController:anotherViewController animated:YES];! // [anotherViewController release];! editingMovie = [moviesArray objectAtIndex:indexPath.row];! movieEditor.movie = editingMovie;! [self.navigationController pushViewController:movieEditor animated:YES];}
  • Due commenti velociAbbiamo istanziato una variabile di tipo MovieQuesta memorizza il contenuto dell’ArrrayQuesto contenuto è poi passato al campo movie del VCLa proprietà navigationController è ereditata da RVCQuesta proprietà cerca all’interno della gerarchia fino a trovareun riferimento ad un UINavigationController
  • Il pulsante DonePer l’IBAction done: bisogna cambiare il comportamentoIn questo caso sarà necessario chiamare il popViewControllerCon la proprietà animated: settata a YES;Anche MEVC può accedere alla proprietà ereditata dalnavigationControllerOra il RVC ottiene il callback a viewWillAppear: e aggiorniamola view
  • viewWillAppear: - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];! NSLog (@"viewWillAppear");! // update table view if a movie was edited! if (editingMovie) {! ! NSIndexPath *updatedPath = [NSIndexPath! ! ! indexPathForRow: [moviesArray indexOfObject: editingMovie] inSection: 0];! ! NSArray *updatedPaths = [NSArray arrayWithObject:updatedPath];! ! [self.tableView reloadRowsAtIndexPaths:updatedPaths withRowAnimation:NO];! ! editingMovie = nil;! }} Identifichiamo la fase di modifica Identifichiamo la riga di tabella aggiornata Otteniamo l’indice dell’arra y corrispondente a editingMovie Creiamo un NSIndexPath a quella riga e ricarichiamo la riga
  • Aggiungiamo un elemento Prima abbiamo usato leftBarButtonItem Ora per il pulsante Aggiungi definiamo una IBAction in RVC.h-(IBAction) handleAddTapped; In IB trascinare su RVC un UIBarButtonItem La connessione avviene in questo caso diversamente Il metodo selector viene richiamato sull’oggetto target L’oggetto target in questo caso è proprio il RVC
  • Implementiamo l’azione -(IBAction) handleAddTapped {! NSLog (@"handleAddTapped");! Movie *newMovie = [[Movie alloc] init];! [moviesArray addObject: newMovie];! editingMovie = newMovie;! movieEditor.movie = editingMovie;! [self.navigationController pushViewController:movieEditor animated:YES];! // update UITableView (in background) with new member! NSIndexPath *newMoviePath = [NSIndexPath indexPathForRow: [moviesArray count]-1 inSection:0];! NSArray *newMoviePaths = [NSArray arrayWithObject:newMoviePath];! [self.tableView insertRowsAtIndexPaths:newMoviePaths withRowAnimation:NO];}
  • LA NAVIGAZIONE
  • Come funziona la navigazioneC’è un Navigation ControllerLa navigazione è organizzata con uno stackTipicamente si parte da RootViewControllerSi passa ad una serie più o meno infinita di altri VCOgnuno riporta un titolo ed un link al precedenteSi passa dal generale al particolare
  • Esaminiamo le coseApriamo un nuovo progetto chiamato DVDCaseAndiamo a vedere MainWindow.xibEsaminiamo il Navigation controllerTroviamo finalmente la Table ViewNotiamo che sia dataSource che delegate sono del File’s Owner
  • Piccole modifiche Sono implementati i metodi numberOfRowInSection: e cellForRowAtIndexPath: li modifichiamo leggermente:- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // return 0;! return 2;} In questo caso abbiamo solo due sezioni
  • Comportamento del VC Invece modifichiamo alcune righe - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) {! cell = [[[UITableViewCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:CellIdentifier]! ! autorelease]; } cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; switch (indexPath.row) { case 0: cell.textLabel.text = @"Home"; break; case 1: cell.textLabel.text = @"Work"; break; default: break; } return cell;}
  • Altre modifiche Andiamo a implementare didSelectRowAtIndexPath:- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath { if(0 == indexPath.row) { self.cabinetController.key = @"home"; self.cabinetController.title = @"Home"; } else { self.cabinetController.key = @"work"; self.cabinetController.title = @"Work"; } [self.navigationController pushViewController:self.cabinetController animated:YES];} Impostiamo il titolo in maniera condizionale Creeremo anche il VC CabinetController
  • PrecisazioniAbbiamo impostato il titolo del VC in maniera condizionaleLa chiamata a pushViewController rende attiva la view del VCLa proprietà cabinetController va dichiarata al RVCAggiungiamo una variabile istanza e un’istruzione @synthesizeModifichiamo viewDidLoad: per visualizzare il testo nel pulsante
  • Personalizzazione - (void)viewDidLoad { [super viewDidLoad];! self.title = @"Cases";} Ora creiamo il VC cabinetController Vedremo che è possibile personalizzare qualcosa in più Possiamo aggiungere un bottone a sx Istanza personalizzata di UIBarButtonItem Con customView si potrebbe sostituire del tutto la view
  • Creiamo il nuovo VCCreiamo una sottoclasse di UITableViewControllerCreiamo il nuovo file NIB che contiene l’interfaccia utenteConfigurare il file NIB per avere una TV e al nostro VCAggiungere un outlet in RVC per farle conoscere il nuovo VCAggiornare RVC.xib per impostare questo outlet
  • Aggiungiamo quello che serve Aggiungiamo un file sottoclasse di UITableViewController Chiamiamola DVDCabinetController Aggiungiamo il nuovo outlet a RVC, aggiungiamo import e synth@class DVDCabinetController;@interface RootViewController : UITableViewController {! DVDCabinetController *cabinetController;}@property(nonatomic, retain) IBOutlet DVDCabinetController *cabinetController;@end
  • ModifichePer connettere l’outlet, apriamo RVC.xib e aggiungiamo un VCImpostare la classe DVDCabinetController nella finestraIdentityConnettere il File’s Owner all’outlet cabinetControllerCreiamo una nuova View da Add->New File, View XIBSostituiamo la UIView con una UITableViewImpostiamo come classe dell’oggetto File’s Owner DVDCC
  • Connettiamo gli oggettiCreiamo le connessioni necessarieTrasciniamo dall’outlet view del F’sO al nuovo oggettoTableViewScegliere l’outlet viewConnettere dataSource e delegate al File’s OwnerPer visualizzare i dati è necessario implementare i soliti 2 metodi
  • Implementiamo Nel file DVDCabinetController.h@interface DVDCabinetController : UITableViewCell {! NSDictionary *data;! NSString *key;}@property (nonatomic, retain) NSString *key; Nel file DVDCabinetController.m-(void)viewDidLoad {! [super viewDidLoad];! NSArray *keys = [NSArray arrayWithObjects:@"Home",@"Work", nil];! NSArray *homeDVDs = [NSArray arrayWithObjects:@"Thomas the Builder", nil];! NSArray *workDVDs = [NSArray arrayWithObjects:@"Intro to Blender",nil];! NSArray *values = [NSArray arrayWithObjects:homeDVDs, workDVDs, nil];! data = [[[NSDictionary alloc] initWithObjects: values forKeys: keys];!}
  • Ultimi ritocchiAbbiamo fatto due dizionari per contenere i valori memorizzatiin RVCTipicamente non si usa questo tipo di approccioRisulta però così più leggibile il codiceModifichiamo i metodi per il ritorno del numero di valoriE personalizziamo la cella affinché mostri il valore corretto
  • Ancora modifiche - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [[data valueForKey:self.key]count];}// Customize the appearance of table view cells.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } // Configure the cell...! cell.textLabel.text = [[data valueForKey:self.key] objectAtIndex:indexPath.row];! return cell;}
  • Ultima porzione di codice Finiamo due modifiche per viewWillAppear:- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];! [self.tableView reloadData];} E tableView:didSelectRowAtIndexPath:- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Navigation logic may go here. Create and push another view controller.! [self.navigationController popViewControllerAnimated:YES];} Finalmente torniamo indietro nella navigazione tramite il riferimento al NavigationController
  • MAPKIT
  • Cosa fa MapKitÈ la classe che si occupa della generazione di mappeÈ particolarmente utile in virtù della localizzazione del deviceUnendo le due funzionalità si possono ottenere ottimi risultatiLa nostra piccola applicazione centrerà la mappa sulla nostraposizione corrente
  • Primo passoCome prima cosa è necessario aggiungere al progetto iFrameworkCreiamo un nuovo progetto e chiamiamolo FindMeUtilizziamo il template View-Based ApplicationAggiungiamo i Framework MapKit e CoreLocationApriamo il file NIB e trascinate un MapView
  • Quasi finitoAbbiamo quasi finito, basta selezionare Show User LocationSelezioniamo il tipo di mappa (Map)Salviamo e eseguiamoIl simulatore mostrerà una posizione fittizia sull’Apple CampusOra vogliamo che la mappa venga centrata nuovamente eingrandita
  • Centrare le mappePer centrare le mappe bisogna usare il metodo setRegion:Il parametro region: è una struttura C simile a CGRectMKCoordinateRegion ha due parti center e span.centerIl primo è un CLocationCoordinate2D con coordinate del puntoIl secondo è un MKCoordinateSpan e specifica la variazione ingradi delle coordinate della regione da includereCentriamo la mappa con .15 di differenza tra le due misure
  • Codice per centrare le mappe - (void)setCurrentLocation:(CLLocation *)location { MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}}; region.center = location.coordinate; region.span.longitudeDelta = 0.15f; region.span.latitudeDelta = 0.15f; [self.mapView setRegion:region animated:YES];} Il Codice è abbastanza autoesplicativo, settiamo la regione Prendiamo le coordinate della nostra posizione Impostiamo anche lo span Diciamo alla mappa di settarsi con un’animazione Impostiamo anche un IBOutlet nel codice per MKView
  • Aggiungere annotazioniInseriamo MKMapView *_mapView; nel file .h,Chiamiamo l’IBOutlet nella stessa manieraE poi sintetizziamo dicendo che _mapView = mapView;Teoricamente dovremo vedere anche il delegato del localizzatoreIn realtà Show User Location farà il lavoro per noiPer le annotazioni MKAnnotation non definisce leimplementazioni pubbliche
  • Le annotazioniPer aggiungere un’annotazione dobbiamo creare la nostraspecifica implementazione di questo protocolloIl protocollo definisce una proprietà e due metodi opzionaliLa proprietà è la localizzazione dell’annotazioneI metodi sono title e subtitleVengono presentati sull’annotazione entrambiUno il titolo, uno il sottotitolo
  • Creiamo un modello Creiamo una classe che implementa <MKAnnotation>#import <Foundation/Foundation.h>#import <CoreLocation/CoreLocation.h>#import <MapKit/MapKit.h>@interface ContactAnnotation : NSObject <MKAnnotation> { CLLocationCoordinate2D _coordinate; NSString *_title; NSString *_subtitle;}+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coordinate;- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate;@property (nonatomic, assign) CLLocationCoordinate2D coordinate;@property (nonatomic, copy) NSString *title;@property (nonatomic, copy) NSString *subtitle;@end Abbiamo definito il nostro protocollo, ora tocca alle classi
  • Il file d’implementazione Andiamo a implementare il protocollo nel nostro file:#import "ContactAnnotation.h"@implementation ContactAnnotation@synthesize coordinate = _coordinate;@synthesize title = _title;@synthesize subtitle = _subtitle;+ (id)annotationWithCoordinate:(CLLocationCoordinate2D)coordinate { return [[[[self class] alloc] initWithCoordinate:coordinate] autorelease];}- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate { self = [super init]; if(nil != self) { self.coordinate = coordinate; } return self;}@end
  • Aggiungere un’azione Teoricamente potremmo decidere di scatenare un’azione alla pressione del tasto Definiamo l’IBAction choose: come segue- (IBAction)choose { UINavigationController *detailView = [[UINavigationController alloc] init]; detailView.viewDelegate = self; [self presentModalViewController:detailView animated:YES]; [detailView release];} Aggiungiamo la definizione nel file header e creiamo la connessione al File’s Owner
  • Aggiungiamo la nota alla mappaNel metodo viewDidApper: possiamo inserire l’animazionePossiamo inserire la nostra istanza di ContactAnnotationIstanziamo la classe da qualche parte nel codice dove più ci serveself.newAnnotation= [ContactAnnotationannotationWithCoordinate:coordinate];Chiamiamo il metodo d’inserimento con [self.mapViewaddAnnotation:sel.newAnnotation];
  • ALLA PROSSIMA LEZIONE!