{"id":5545,"date":"2010-12-28T17:14:54","date_gmt":"2010-12-28T16:14:54","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=5545"},"modified":"2011-01-10T18:18:28","modified_gmt":"2011-01-10T17:18:28","slug":"t083-aggiungiamo-funzionalita-agli-oggetti-le-categorie","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t083-aggiungiamo-funzionalita-agli-oggetti-le-categorie\/","title":{"rendered":"T#083 &#8211; Aggiungiamo funzionalit\u00e0 agli oggetti:  Le categorie"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Categories-objective-c-xcode-Icon.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Categories-objective-c-xcode-Icon.png\" alt=\"t083-Categories-objective-c-xcode-Icon\" title=\"t083-Categories-objective-c-xcode-Icon\" width=\"128\" height=\"128\" class=\"alignleft size-full wp-image-5546\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Categories-objective-c-xcode-Icon.png 128w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Categories-objective-c-xcode-Icon-90x90.png 90w\" sizes=\"auto, (max-width: 128px) 100vw, 128px\" \/><\/a> Alcune volte \u00e8 necessario presentare un oggetto generico che eredita da UIView in maniera esclusiva sullo schermo, per richiamare l&#8217;attenzione o semplicemente per mostrare una scelta &#8220;obbligata&#8221; all&#8217;utente. UIKit di Cocoa, ci mette a disposizione la classe UIAlertView proprio per questo scopo. Purtroppo, il suo funzionamento \u00e8 molto restrittivo in termini di personalizzazione da parte dell&#8217;utente e come funzionalit\u00e0 offerte.<br \/>\nIn quest&#8217;articolo, sfrutteremo questa esigenza per prendere confidenza con una tecnica di programmazione molto particolare di Objective-C: Le categorie.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/clk.tradedoubler.com\/click?p=24373&#038;a=1735897&#038;g=0&#038;url=http:\/\/itunes.apple.com\/it\/app\/auto-e-moto-rubate\/id370077839?mt=8&#038;partnerId=2003\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate.jpg\" alt=\"bn_auto-e-moto-rubate-app-iphone\" title=\"bn_auto-e-moto-rubate\" width=\"468\" height=\"54\" class=\"aligncenter size-full wp-image-5551\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate.jpg 468w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate-300x34.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate-150x17.jpg 150w\" sizes=\"auto, (max-width: 468px) 100vw, 468px\" \/><\/a><br \/>\n<\/center><br \/>\n<!--more--><\/p>\n<h4>Introduzione alle categorie<\/h4>\n<p>Le categorie sono un potente strumento, fornito agli sviluppatori Objective-C, per estendere le funzionalit\u00e0 degli oggetti messi a disposizione del programmatore. A differenza delle sottoclassi, permettono di specializzare il comportamento di un oggetto senza dover scendere in dettagli tecnici relativi alla classe stessa. Una categoria permette di estendere immediatamente il comportamento di una determinata classe; l&#8217;estensione sar\u00e0 immediatamente disponibile in tutte le classi (e sottoclassi) che ereditano dall&#8217;oggetto di cui stiamo estendendo le funzionalit\u00e0.<\/p>\n<p>Come in Javascript con l&#8217;estensione dei metodi, le categorie permettono al programmatore di aggiungere funzionalit\u00e0 al codice di una classe, senza per questo esserne gli sviluppatori originali e\/o in possesso del codice sorgente. In linea di principio, \u00e8 possibile estendere il comportamento di una classe\/oggetto, semplicemente creando una categoria per questo scopo. A differenza del concetto di sottoclasse, le categorie possono essere cumulative, nel senso che pi\u00f9 categorie possono essere sommate per aggiungere funzionalit\u00e0 diverse alla stessa classe. Quindi, una classe pu\u00f2 essere estesa contemporaneamente da pi\u00f9 categorie che, insieme, concorrono a fornire nuove caratteristiche all&#8217;oggetto base.<br \/>\n\tPer creare una categoria \u00e8 necessario implementare una porzione di codice dichiarativo (header file .h) ed una porzione di codice implementativo (implementation file .m). Il nostro file di header, quindi, conterr\u00e0 un prologo dichiarativo su quello che stiamo per fare; in pratica, informeremo il compilatore che stiamo per estendere la classe UIView, ad esempio, con delle nuove funzionalit\u00e0 (metodi d&#8217;istanza). Conseguentemente, il file di implementazione conterr\u00e0 l&#8217;implementazione di questi metodi e delle funzionalit\u00e0 dichiarate in precedenza.<\/p>\n<h4>Nuove funzionalit\u00e0 per le UIView<\/h4>\n<p>Ogni oggetto che eredita da UIView pu\u00f2 essere aggiunto, a sua volta, come subview all&#8217;interno di un&#8217;altro oggetto UIView padre, attraverso l&#8217;uso del metodo d&#8217;istanza: -(void)addSubview:<br \/>\nIl nostro obiettivo \u00e8 quello di aggiungere una specializzazione a questo comportamento per presentare il nuovo oggetto in maniera gradevole, ad esempio mostrandolo come pop-up al centro dello schermo e rendendolo reattivo al tocco dell&#8217;utente. Alla pressione su di esso, infatti, vorremmo che scompaia in maniera altrettanto &#8220;gradevole&#8221; dallo schermo. La figura sotto, illustra il concetto che stiamo per realizzare programmaticamente.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode.jpg\" alt=\"t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode\" title=\"t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode\" width=\"368\" height=\"716\" class=\"aligncenter size-full wp-image-5547\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode.jpg 368w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode-154x300.jpg 154w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t083-Aggiungiamo-funzionalita-agli-oggetti-Le-categorie-objective-c-xcode-77x150.jpg 77w\" sizes=\"auto, (max-width: 368px) 100vw, 368px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Visto che non abbiamo ancora chiaro da &#8220;quale&#8221; classe erediteremo per il nostro oggetto modale da presentare o, semplicemente, se vogliamo dotare &#8220;tutti&#8221; gli oggetti che  ereditano da UIView di queste caratteristiche, utilizzeremo una categoria. Quest&#8217;ultima estender\u00e0 il comportamento di tutti gli oggetti che ereditano da UIView, in maniera istantanea, con due nuovi metodi:<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n-(void) pushViewTo:(UIView *)aView;\r\n-(void)removeFromView;\r\n<\/pre>\n<p>Il primo metodo si occuper\u00e0 di mostrare il nostro oggetto all&#8217;interno del contenitore padre passato come parametro. Il secondo metodo, si preoccuper\u00e0 di rimuoverlo dal contenitore padre e distruggerlo dalla memoria. La parte di dichiarazione, che andr\u00e0 nel file di hedear (.h), sar\u00e0 cos\u00ec composta:<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n@interface UIView (animation)\r\n\r\n-(void) pushViewTo:(UIView *)aView;\r\n-(void)removeFromView;\r\n\r\n@end\r\n<\/pre>\n<p>I metodi dichiarati sono gli unici pubblici e, quindi, gli unici che verranno esposti a tutte le classi  estese dalla categoria. La prima riga ci dice che stiamo estendendo la classe UIView, creando una categoria chiamata animation. Le successive due righe, racchiuse prima della parola chiave @end, indicano i metodi che creeremo nell&#8217;apposito file d&#8217;implementazione.<br \/>\nA differenza delle normali dichiarazioni di interfacce di classe, qui non \u00e8 possibile dichiarare delle variabili di istanza. L&#8217;unica cosa che possiamo fare \u00e8 dichiarare i metodi che popoleranno la nostra categoria e che andranno ad estendere il comportamento standard della classe. La parte implementativa (.m) sar\u00e0 costituita di conseguenza:<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n@implementation UIView (animation) \r\n\r\n-(void) pushViewTo:(UIView *)aView {\r\n\t\u2026\r\n\t\u2026\r\n}\r\n\r\n-(void)removeFromView {\r\n\t\u2026\r\n\t\u2026\r\n}\r\n\r\n@end\r\n<\/pre>\n<h4>Popoliamo i nostri metodi<\/h4>\n<p>A questo punto resta da implementare il codice per ognuno dei metodi sopra. In quest&#8217;esempio, vogliamo che l&#8217;oggetto UIView, compaia dal centro dell&#8217;oggetto padre e si ingrandisca gradualmente, con un effetto molla:<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n-(void) pushViewTo:(UIView *)aView {\r\n\t\/\/Creiamo una matrice di trasformazione che scala la dimensione originale a zero\r\n\tCGAffineTransform transform = CGAffineTransformMakeScale(0.1, 0.1);\r\n\tself.transform = transform;\r\n\r\n\t\/\/Abilitiamo l'interazione utente sull'oggetto\r\n\tself.userInteractionEnabled = YES;\r\n\r\n\t\/\/Aggiungiamo l'oggetto al padre (aView) e posizioniamolo al centro\r\n\t[aView addSubview:self];\r\n\tself.center = CGPointMake(160, 240);\r\n\r\n\t\/\/Iniziamo un contesto CoreAnimation\r\n\t[UIView beginAnimations:@\"pushViewToScreen\" context:nil];\r\n\t[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];\r\n\t[UIView setAnimationDuration:0.3];\r\n\r\n\t\/\/Impostiamo come delegato la categoria stessa!\r\n\t[UIView setAnimationDelegate:self];\r\n\t\r\n\t\/\/Al completamento della prima parte dell'animazione, lanciamo la seconda.\r\n\t[UIView setAnimationDidStopSelector:@selector(pushViewToSecondPart)];\r\n\r\n\t\/\/ Tutto il codice racchiuso nel contesto d'animazione verr\u00e0 automaticamente\r\n\t\/\/ animato con keyframes.\r\n\tCGAffineTransform transform2 = CGAffineTransformMakeScale(1.1, 1.1);\r\n\tself.transform = transform2;\r\n\r\n\t[UIView commitAnimations];\r\n}\r\n<\/pre>\n<p>Resta da implementare il metodo di scomparsa dallo schermo: -(voi)removeFromView. Per ottenere un simpatico effetto molla, dobbiamo &#8220;spezzare&#8221; l&#8217;animazione in tre fasi distinte: ingradimento, rimpicciolimento, scomparsa.<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n-(void)removeFromView {\r\n\t[UIView beginAnimations:@\"removeFromView\" context:nil];\r\n\t[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];\r\n\t[UIView setAnimationDuration:0.3];\r\n\t[UIView setAnimationDelegate:self];\r\n\t[UIView setAnimationDidStopSelector:@selector(removeFromViewSecondPart)];\r\n\tCGAffineTransform transform2 = CGAffineTransformMakeScale(1.1, 1.1);\r\n\tself.transform = transform2;\r\n\t[UIView commitAnimations];\r\n\t\r\n}\r\n\r\n-(void)removeFromViewSecondPart {\r\n\t[UIView beginAnimations:@\"removeFromViewSecondPart\" context:nil];\r\n\t[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];\r\n\t[UIView setAnimationDuration:0.3];\r\n\t[UIView setAnimationDelegate:self];\r\n\t[UIView setAnimationDidStopSelector:@selector(removeFromViewThirdPart)];\r\n\tCGAffineTransform transform2 = CGAffineTransformMakeScale(0.1, 0.1);\r\n\tself.transform = transform2;\r\n\t[UIView commitAnimations];\r\n}\t\r\n\r\n-(void)removeFromViewThirdPart {\r\n\t[self removeFromSuperview];\r\n}\r\n<\/pre>\n<h4>Ancora una cosa: Il controllo del tocco. Categorie e delegati<\/h4>\n<p>Resta da implementare un&#8217;ultima caratteristica. L&#8217;oggetto presentato a schermo dovrebbe rispondere al tocco dell&#8217;utente, reagendo con la scomporsa \/ rimozione di se stesso. Questo ci offre un utile spunto per illustrare un&#8217;interessante caratteristica delle categorie.<br \/>\nLe categorie, come una normale classe, possono implementare metodi delegati rendendoli disponibili a tutte le classi (o sottoclassi) che stiamo estendendo. Categorie e delegati, quindi, possono coesistere ed insieme possono collaborare nell&#8217;estendere il comportamento di una classe. Nel nostro caso specifico, implementeremo all&#8217;interno della categoria un metodo delegato per la gestione del tocco utente: <\/p>\n<pre lang=\"objc\" line=\"1\">\r\n- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event\r\n<\/pre>\n<p>Ci baster\u00e0 verificare che il tocco sia stato effettuato sull&#8217;oggetto stesso (self) ed, in caso affermativo, lanciare il metodo di rimozione dallo schermo definito sopra:<\/p>\n<pre lang=\"objc\" line=\"1\">\r\n#pragma mark UITouch events\r\n- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {\r\n    UITouch *touch = [touches anyObject];\r\n    if (touch.view == self)\r\n        [self removeFromView];\r\n}\r\n<\/pre>\n<p>A questo punto, il nostro oggetto UIView \u00e8 stato specializzato con una categoria animation che ne rende l&#8217;apparizione e la scomparsa dallo schermo molto gradevole. Visto che abbiamo esteso il comportamento della classe UIView, qualunque altro oggetto che eredita da UIView, potr\u00e0 usare i nostri nuovi metodi di apparizione e scomparsa. Ad esempio, un oggetto UIImageView le potr\u00e0 sfruttare a suo vantaggio per mostrare un&#8217;immagine a schermo. Nel codice d&#8217;esempio fornito troverete due esempi, uno con UIView ed uno con UIImageView. Entrambi gli oggetti ereditano le stesse primitive.<br \/>\nL&#8217;uso delle categorie non si ferma solo a questo ma, avere ben chiaro qual&#8217;e&#8217; lo scopo principale per cui \u00e8 stato pensato questo pattern di programmazione, render\u00e0 pi\u00f9 semplice l&#8217;apprendimento di tecniche avanzate d&#8217;uso.<\/p>\n<p>Non mi resta che salutarvi e ringraziarvi per l&#8217;attenzione. Buone feste e felice anno nuovo!<\/p>\n<p>Costantino Pistagna<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CategoriesTutorial.zip\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/05\/download_icon.png\" alt=\"\" width=\"33\" height=\"40\" align=\"middle\" \/><\/a> Se avete problemi con il tutorial, <a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CategoriesTutorial.zip\">questo \u00e8 il nostro file di progetto.<\/a><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/clk.tradedoubler.com\/click?p=24373&#038;a=1735897&#038;g=0&#038;url=http:\/\/itunes.apple.com\/it\/app\/auto-e-moto-rubate\/id370077839?mt=8&#038;partnerId=2003\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate.jpg\" alt=\"bn_auto-e-moto-rubate-app-iphone\" title=\"bn_auto-e-moto-rubate\" width=\"468\" height=\"54\" class=\"aligncenter size-full wp-image-5551\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate.jpg 468w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate-300x34.jpg 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/bn_auto-e-moto-rubate-150x17.jpg 150w\" sizes=\"auto, (max-width: 468px) 100vw, 468px\" \/><\/a><br \/>\n<\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alcune volte \u00e8 necessario presentare un oggetto generico che eredita da UIView in maniera esclusiva sullo schermo,&#8230;<\/p>\n","protected":false},"author":476,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[529,531,528,530,533,479,532,293,63],"class_list":["post-5545","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-addsubview","tag-beginanimations","tag-categorie","tag-cgaffinetransform","tag-coreanimation","tag-costantino-pistagna","tag-setanimation","tag-touchesbegan","tag-uiview"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5545","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\/476"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=5545"}],"version-history":[{"count":8,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5545\/revisions"}],"predecessor-version":[{"id":5610,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5545\/revisions\/5610"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=5545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=5545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=5545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}