{"id":3350,"date":"2010-05-11T09:50:30","date_gmt":"2010-05-11T07:50:30","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=3350"},"modified":"2012-02-13T10:50:01","modified_gmt":"2012-02-13T09:50:01","slug":"t041-usiamo-le-uitableview-parte-3-implementiamo-la-barra-di-ricerca","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t041-usiamo-le-uitableview-parte-3-implementiamo-la-barra-di-ricerca\/","title":{"rendered":"T#041 \u2013 Usiamo le UITableView (parte 3): Implementiamo la barra di ricerca"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-3354\" title=\"Immagine 3\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png\" alt=\"\" width=\"52\" height=\"96\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png 414w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31-161x300.png 161w\" sizes=\"auto, (max-width: 52px) 100vw, 52px\" \/> Siamo giunti al terzo appuntamento riguardante le UITableView, ovvero le tabelle presenti nell&#8217;SDK per iPhone. Negli scorsi tutorial abbiamo visto come\u00a0creare e popolare una tabella (<a href=\"http:\/\/www.devapp.it\/wordpress\/t039-usiamo-le-uitableview-parte-1-creiamo-e-popoliamo-le-nostre-tabelle.html\" target=\"_blank\">Parte I<\/a>) e come\u00a0aggiungere alcune funzionalit\u00e0, come la possibilit\u00e0 di editare (nel nostro caso cancellare) alcune celle e intercettare il tocco dell&#8217;utente (<a href=\"http:\/\/www.devapp.it\/wordpress\/t040-usiamo-le-uitableview-parte-2-modifichiamo-le-celle-e-intercettiamone-il-tocco.html\" target=\"_blank\">Parte II<\/a>). In questa nuova parte vedremo, invece, come aggiungere una funzionalit\u00e0 molto importante: <strong>la ricerca<\/strong>.<!--more--><\/p>\n<h4>1. Inseriamo la barra di ricerca<\/h4>\n<p>Facciamo doppio clic sul file &#8220;RootViewController.xib&#8221; per aprire IB, e inseriamo la nostra barra di ricerca. Anche in questo caso, grazie al firmware 3.0, sono state apportate delle migliorie nelle API che gestiscono la ricerca nelle tabelle. Dalla Libreria selezioniamo il componente &#8220;<strong>Search Bar and Search Display Controller<\/strong>&#8221; e trasciniamolo sopra l&#8217;elemento &#8220;Table View&#8221; che vedete nel Pannello dei documenti.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-12.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-3352\" title=\"Immagine 1\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-12-300x207.png\" alt=\"\" width=\"300\" height=\"207\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-12-300x207.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-12.png 667w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Se avete eseguito tutto correttamente la vostra tabella mostrer\u00e0 ora anche una barra di ricerca:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-21.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3353\" title=\"Immagine 2\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-21.png\" alt=\"\" width=\"400\" height=\"582\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-21.png 400w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-21-206x299.png 206w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-21-103x149.png 103w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3354\" title=\"Immagine 3\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png\" alt=\"\" width=\"414\" height=\"770\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png 414w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31-161x300.png 161w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31-80x150.png 80w\" sizes=\"auto, (max-width: 414px) 100vw, 414px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Ancora una volta davvero tutto molto semplice!<\/p>\n<p>Salvate tutto e chiudere Interface Buider.<\/p>\n<h4>2. Modifichiamo i metodi gi\u00e0 esistenti<\/h4>\n<p>Prima di implementare la ricerca vera e propria, dobbiamo fare delle piccole modifiche ai metodi gi\u00e0 presenti nel nostro progetto.<br \/>\nIniziamo aprendo il file &#8220;RootViewController.h&#8221; e completiamo cos\u00ec la definizione della classe:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@interface RootViewController : UITableViewController {\r\n\tNSMutableArray *lista;\r\n\tNSMutableArray *filteredListContent;\r\n}\r\n\r\n@property (nonatomic, retain) NSMutableArray *lista;\r\n@property (nonatomic, retain) NSMutableArray *filteredListContent;\r\n\r\n@end\r\n<\/pre>\n<p>Abbiamo semplicemente dichiarato una nuova lista (riga 3), che conterr\u00e0 gli elementi &#8220;filtrati&#8221;, ovvero quelli che corrispondono al criterio di ricerca.<\/p>\n<p>Ora dobbiamo modificare i metodi che si occupano dell&#8217;inizializzazione della tabella. Iniziamo dal metodo &#8220;viewDidLoad&#8221; e dalla funzione &#8220;@synthetize&#8221;:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import \"RootViewController.h\"\r\n\r\n@implementation RootViewController\r\n\r\n@synthesize lista, filteredListContent;\r\n\r\n- (void)viewDidLoad {\r\n    [super viewDidLoad];\r\n\r\n\tself.title = @\"Prodotti Apple\";\r\n\r\n\t\/\/elementi da visualizzare nella tabella\r\n\tlista = [[NSMutableArray alloc] initWithObjects:@\"iPhone\", @\"iPod\",\r\n\t\t\t @\"iPod Touch\", @\"iMac\", @\"iBook\", @\"MacBook\", @\"MacBook Pro\", @\"Mac Pro\",\r\n\t\t\t @\"PowerBook\", nil]; \r\n\r\n    \/\/ Uncomment the following line to display an Edit button in the navigation bar for this view controller.\r\n    self.navigationItem.rightBarButtonItem = self.editButtonItem;\r\n\r\n\t\/\/ crea la lista filtrata, inizializzandola con il numero di elementi dell'array \"lista\"\r\n\tfilteredListContent = [[NSMutableArray alloc] initWithCapacity: [lista count]];\r\n\t\/\/inserisce in questa  nuova lista gli elementi della lista originale\r\n\t[filteredListContent addObjectsFromArray: lista];\r\n}\r\n<\/pre>\n<p>Come potete vedere la prima parte del metodo &#8220;viewDidLoad&#8221; \u00e8 uguale a quella che gi\u00e0 abbiamo scritto nei precedenti tutorial. Alle righe 21 e 23, invece, abbiamo definito due istruzioni, che hanno il compito di inizializzare il nuovo array, che ci servir\u00e0 nell&#8217;algoritmo di ricerca. Inizialmente questa lista coincider\u00e0 con quella degli elementi iniziali, successivamente verr\u00e0 modificata durante la digitazione dell&#8217;utente della stringa di ricerca.<\/p>\n<p>Il secondo metodo da modificare \u00e8 &#8220;numberOfRowsInSection&#8221;. Ecco il nuovo codice:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{\r\n\t\/\/il numero di righe deve corrispondere al numero di elementi della lista\r\n\treturn [filteredListContent count];\r\n}\r\n<\/pre>\n<p>Questa modifica va eseguita in quanto la tabella ora non \u00e8 pi\u00f9 composta dagli elementi della lista originale, ma da quelli della lista filtrata, ovvero da quegli elementi selezionati mediante la ricerca. Ovviamente se l&#8217;utente non esegue nessuna ricerca, gli elementi della lista filtrata corrisponderanno agli elementi della lista originale.<\/p>\n<p>Se vi \u00e8 chiaro questo ragionamento, \u00e8 facile intuire quali saranno i prossimi metodi da modificare: il primo \u00e8 &#8220;cellForRowAtIndexPath:&#8221;, ovvero il metodo che si occupa di inserire i valori nelle celle. Modificate l&#8217;ultima istruzione al suo interno nella seguente maniera:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n\/\/inseriamo nella cello l'elemento della lista corrispondente\r\ncell.textLabel.text = [filteredListContent objectAtIndex:indexPath.row];\r\n<\/pre>\n<p>Modifichiamo, poi, il metodo &#8220;commitEditingStyle&#8221; modificando l&#8217;istruzione presente alla riga 4:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n\/\/controlla se l'azione compiuta \u00e8 un'eliminazione\r\n\tif (editingStyle == UITableViewCellEditingStyleDelete) {\r\n\t\t\/\/elimina l'elemento dalla lista\r\n\t\t[filteredListContent removeObjectAtIndex:indexPath.row];\r\n\t\t\/\/elimina le'elemento dalla tabella\r\n\t\t[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];\r\n\r\n\t}\r\n<\/pre>\n<p>L&#8217;ultimo metodo da modificare, infine, \u00e8 &#8220;didSelectRowAtIndexPath:&#8221; e anche in questo caso l&#8217;unica modifica riguarda proprio la lista di riferimento:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n\/\/ Se selezioniamo una riga appare un pop-up con l'elemento in questione\r\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {\r\n\tUIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@\"Hai selezionato:\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tmessage:[filteredListContent objectAtIndex:indexPath.row] delegate:self cancelButtonTitle:@\"OK\" otherButtonTitles:nil];\r\n\t[popUp show];\r\n\t[popUp release];\r\n}\r\n<\/pre>\n<p>Abbiamo cos\u00ec eseguito tutte le modifiche necessarie!<\/p>\n<h4>3. Implementiamo la ricerca<\/h4>\n<p>\u00c8 arrivato il momento di implementare la ricerca vera e propria. Prima di mostrarvi i passaggi necessari, devo premettere che il codice non \u00e8 stato scritto da me, ma l&#8217;ho preso da un esempio realizzato dalla stessa Apple. I commenti, quindi, saranno davvero pochi, anche perch\u00e8 non \u00e8 fondamentale capire come funziona tale algoritmo, in quanto lo stesso codice si pu\u00f2 utilizzare in qualsiasi altra applicazione che necessiti di una ricerca.<\/p>\n<p>Iniziate inserendo questi due metodi:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{\r\n    [self filterContentForSearchText:searchString scope:\r\n\t [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];\r\n\r\n    \/\/ Return YES to cause the search result table view to be reloaded.\r\n    return YES;\r\n}\r\n\r\n- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption{\r\n\r\n    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:\r\n\t [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];\r\n\r\n    \/\/ Return YES to cause the search result table view to be reloaded.\r\n    return YES;\r\n}\r\n<\/pre>\n<p>I due metodi appena mostrati fanno parte del delegato &#8220;UISearchDisplayController&#8221;, che si occupa di gestire in maniera corretta la barra di ricerca.<\/p>\n<p>Dobbiamo inserire, inoltre, un metodo che si occupa di reinserire tutti gli elementi originali nell&#8217;array filtrato quando l&#8217;utente annulla la ricerca. Per fare ci\u00f2 ci serviremo del metodo &#8220;searchBarCancelButtonClicked&#8221;, che vieni richiamato proprio quando l&#8217;utente annulla la ricerca tramite il bottone &#8220;Cancel&#8221;:<\/p>\n<pre lang=\"ObjC\" line=\"1\">\r\n- (void)searchBarCancelButtonClicked:(UISearchBar *)saearchBar {\r\n    [self.filteredListContent removeAllObjects];\r\n    [self.filteredListContent addObjectsFromArray: lista];\r\n}\r\n<\/pre>\n<p>Senza questo metodo l&#8217;applicazione crasha quando si annulla una ricerca e si seleziona un elemento che \u00e8 superiore al numero di elementi dell&#8217;ultima ricerca (grazie a Dario per la segnalazione e ad Andrea per la soluzione nei commenti).<\/p>\n<p>Ora dobbiamo inserire l&#8217;algoritmo di ricerca vero e proprio. Eccovelo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{\r\n\r\n\t\/*\r\n\t Update the filtered array based on the search text and scope.\r\n\t *\/\r\n\t[self.filteredListContent removeAllObjects]; \/\/ First clear the filtered array.\r\n\r\n\t\/*\r\n\t Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.\r\n\t *\/\r\n\tNSString *cellTitle;\r\n\tfor (cellTitle in lista){\r\n\t\tNSComparisonResult result = [cellTitle compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])];\r\n\t\tif (result == NSOrderedSame){\r\n\t\t\t[filteredListContent addObject:cellTitle];\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>Per questo algoritmo non voglio spendere parole, in quanto, come detto in precedenza, \u00e8 stato scritto da Apple, quindi non posso permettermi di fare modifiche!<\/p>\n<p>Cliccate ora su &#8220;Build and Go!&#8221;, se avete eseguito tutto correttamente si aprir\u00e0 la vostra applicazione!<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-3354\" title=\"Immagine 3\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png\" alt=\"\" width=\"414\" height=\"770\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31.png 414w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31-161x300.png 161w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/Immagine-31-80x150.png 80w\" sizes=\"auto, (max-width: 414px) 100vw, 414px\" \/><\/a><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/tableViewTutorial_parte3.zip\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/download_icon.png\" alt=\"Icona Download\" title=\"download_icon\" width=\"33\" height=\"40\" class=\"alignnone size-full wp-image-3385\" \/><\/a> Se avete problemi con il tutorial, questo \u00e8 il <a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/tableViewTutorial_parte3.zip\">nostro file di progetto<\/a>.<br \/>\n<\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Siamo giunti al terzo appuntamento riguardante le UITableView, ovvero le tabelle presenti nell&#8217;SDK per iPhone. Negli scorsi&#8230;<\/p>\n","protected":false},"author":254,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[216,88,220,217,221,27],"class_list":["post-3350","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-andrea-busi","tag-programmazione-iphone","tag-ricerca-uitable","tag-tabelle-iphone","tag-uitable-search","tag-uitableview"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/3350","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/254"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=3350"}],"version-history":[{"count":12,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/3350\/revisions"}],"predecessor-version":[{"id":8562,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/3350\/revisions\/8562"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=3350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=3350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=3350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}