{"id":8758,"date":"2012-04-02T14:12:03","date_gmt":"2012-04-02T12:12:03","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=8758"},"modified":"2012-04-02T14:12:03","modified_gmt":"2012-04-02T12:12:03","slug":"t107-le-referenze-associative-aggiungiamo-le-variabili-alle-categorie","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t107-le-referenze-associative-aggiungiamo-le-variabili-alle-categorie\/","title":{"rendered":"T#107 &#8211; Le referenze associative: Aggiungiamo le variabili alle 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>  Una delle caratterestiche pi\u00f9 importanti di Objective-C di cui abbiamo gi\u00e0 parlato in un <a href=\"http:\/\/www.devapp.it\/wordpress\/t083-aggiungiamo-funzionalita-agli-oggetti-le-categorie.html\" target=\"_blank\">precedente articolo<\/a> sono le Categorie. Esse permettono di aggiungere metodi arbitrari ad una classe di cui, ad esempio, non si ha il codice sorgente, specializzandola secondo le nostre esigenze.<br \/>\nAlcune volte risulta necessario aggiungere anche delle variabili d&#8217;istanza alla classe specializzata con le Categorie. In linea di principio questo non \u00e8 possibile e probabilmente indica una cattiva ingegnerizzazione della classe su cui stiamo lavorando. Tuttavia, le referenze associative ci permettono di aggirare questa limitazione, fornendo uno strumento per aggiungere oggetti (variabili d&#8217;istanza) a runtime ad un altro oggetto disponibile durante l&#8217;esecuzione della nostra applicazione. Essenzialmente, questo significa che ogni oggetto ha un dizionario nascosto\/opzionale a cui \u00e8 possibile aggiungere delle coppie chiave\/valore.<br \/>\nQuest&#8217;articolo illustra le tecniche base per poter trarre profitto da questa caratteristica, illustrando due tipici casi d&#8217;uso.<!--more--><\/p>\n<h4>Le Referenze Associative<\/h4>\n<p>Le referenze associative, disponibili a partire da Mac OS X 10.6 ed iOS 3.1, permettono l&#8217;associazione di uno o pi\u00f9 oggetti ad un\u2019altro oggetto istanziato. Utilizzando le referenze associative, quindi, \u00e8 possibile &#8220;attaccare&#8221; uno o pi\u00f9 oggetti ad un altro oggetto senza modificarne la dichiarazione di classe. Questo pattern potrebbe ritornare molto utile quando si lavora, ad esempio, con librerie terze di cui non abbiamo il codice sorgente o quando la categorizzazione della classe necessita dell&#8217;uso di una o pi\u00f9 variabili d&#8217;istanza.<br \/>\nLe associazioni sono basate sul concetto di chiave. E&#8217; possibile aggiungere ad ogni oggetto un numero arbitrario di associazioni, ognuna con una chiave identificativa diversa.<\/p>\n<h4>Creiamo un\u2019associazione<\/h4>\n<p>La funzione messa a disposizione da Objective-C per creare un&#8217;associazione tra un oggetto ed un altro \u00e8 <strong>objc_setAssociatedObject<\/strong>. La funzione prende quattro parametri: l&#8217;oggetto sorgente, una chiave, l&#8217;oggetto da associare ed una costante che indica il tipo di associazione.<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nvoid objc_setAssociatedObject( id object,\r\n                               void *key,\r\n                               id value,\r\n                               objc_AssociationPolicy policy);\r\n<\/pre>\n<p>Riguardo ai parametri object e value, rispettivamente oggetto che riceve l&#8217;associazione ed oggetto da associare, credo ci sia molto poco da chiarire. Quello che invece merita una particolare attenzione sono i parametri key e policy:<\/p>\n<ul>\n<li><strong>key<\/strong> \u00e8 un puntatore void, unico per ogni associazione. Il pattern tipico,<br \/>\nconsigliato da Apple, \u00e8 quello di usare una variabile statica. Qualcosa del tipo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">static char *KEY_IDENTIFIER;<\/pre>\n<p>andr\u00e0 bene per lo scopo che ci siamo preposti. Ricordate che la funzione prende<br \/>\ncome parametro un puntatore all\u2019indirizzo di memoria del CARATTERE.<\/li>\n<li><strong>policy<\/strong> specifica come viene assegnato l&#8217;oggetto associato (retain, copy, nonatomic,atomic). I tipi possibili sono definiti in un enum riportato di seguito:\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nenum {\r\n    OBJC_ASSOCIATION_ASSIGN = 0,\r\n    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,\r\n    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,\r\n    OBJC_ASSOCIATION_RETAIN = 01401,\r\n    OBJC_ASSOCIATION_COPY = 01403\r\n};\r\n<\/pre>\n<p>Valgono le stesse regole esistenti per @property\/@synthesize. Quindi, un oggetto trattenuto (retained) avr\u00e0 il suo reference counter incrementato almeno per tutta la durata di vita dell&#8217;oggetto a cui \u00e8 stato assegnato; assign, permetter\u00e0 di effettuare un&#8217;associazione debole, copy creer\u00e0 una copia dell&#8217;oggetto passato. L&#8217;uso dei parametri NONATOMIC\/ATOMIC, permette di dialogare con circostanze in cui si renda necessario l\u2019uso di concorrenza o meno. Per maggiori informazioni su questo argomento, vi rimando alla documentazione Apple.<\/li>\n<\/ul>\n<h4>Recuperiamo un valore associato<\/h4>\n<p>Per recuperare un valore associato precedentemente ci viene in aiuto la funzione <strong>objc_getAssociatedObject<\/strong>. La funzione prende due parametri: l&#8217;oggetto sorgente da cui si intende recuperare e la chiave dell&#8217;oggetto da recuperare.<br \/>\nRicordate che ad ogni chiave (la variabile statica di cui sopra) pu\u00f2 essere associato uno ed un solo valore. Se intendiamo associare pi\u00f9 di un oggetto con questo metodo, avremo bisogno di pi\u00f9 chiavi dichiarate in forma statica. Approfondiremo questo concetto tra un attimo, quando scriveremo il nostro primo esempio. Il prototipo della funzione di get \u00e8 il seguente:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nvoid objc_getAssociatedObject( id object, void *key);\r\n<\/pre>\n<h4>Un esempio concreto<\/h4>\n<p>Adesso che abbiamo chiaro cosa sono e come si comportano le referenze associative, proviamo a creare un esempio completo che utilizza questa caratteristica. Per iniziare, creeremo una categoria che specializza la classe UIView standard, fornendo un modo per aggiungere un tag arbitrario a questa classe.<\/p>\n<p><strong>Nota:<\/strong> La propriet\u00e0 tag, pre-esistente nell&#8217;oggetto UIView ed ereditata da NSObject, permette gi\u00e0 di associare interi. Questo potrebbe risultare limitativo in molti casi pratici in cui si<br \/>\nnecessita di tagging pi\u00f9 complesso. La categoria creata in quest&#8217;esempio fornisce un metodo risolutivo a questa limitazione.<\/p>\n<p>Apriamo il nostro XCode e creiamo una nuova &#8220;Empty Application&#8221;. Per prima cosa, occupiamoci di creare una nuova categoria che specializzer\u00e0 la classe preesistente UIView. Premiamo <strong>\u2318+N<\/strong> e scegliamo di creare una nuova categoria:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-01.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-01.jpg\" alt=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-01\" title=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-01\" width=\"550\" height=\"370\" class=\"aligncenter size-full wp-image-8762\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-01.jpg 728w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-01-300x201.jpg 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Diamo un nome alla nostra categoria, prestando attenzione che la classe da cui ereditiamo sia impostata in UIView.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-02.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-02.jpg\" alt=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-02\" title=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-02\" width=\"550\" height=\"370\" class=\"aligncenter size-full wp-image-8765\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-02.jpg 728w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-02-300x201.jpg 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>A questo punto modifichiamo il file di dichiarazione aggiungendo una propriet\u00e0 di tipo generico id con cui dialogheremo attraverso l&#8217;uso delle referenze associative:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import <UIKit\/UIKit.h>\r\n@interface UIView (TagObject)\r\n@property (nonatomic, retain) id objectTag;\r\n@end\r\n<\/pre>\n<p>Spostiamoci nel file di implementazione (.m) e modifichiamolo come segue:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import <objc\/runtime.h>\r\n#import \"UIView+TagObject.h\"\r\nstatic char *tagKey;\r\n@implementation UIView (TagObject)\r\n- (id)objectTag {\r\nreturn objc_getAssociatedObject(self, tagKey);\r\n}\r\n- (void)setObjectTag:(id)newObjectTag {\r\nobjc_setAssociatedObject(self,\r\n                         tagKey,\r\n                         newObjectTag,\r\n                         OBJC_ASSOCIATION_RETAIN_NONATOMIC);\r\n}\r\n@end\r\n<\/pre>\n<p>La prima cosa a cui prestare attenzione \u00e8 la nuova direttiva di compilazione inserita in testa al file. Per poter usare le primitive di referenza associativa \u00e8 necessario includere il file di libreria responsabile di tutte le funzioni di runtime: <strong><objc\/runtime.h><\/strong>.<\/p>\n<p>Specifichiamo adesso una variabile <strong>static<\/strong> di tipo puntatore a carattere, prima dell&#8217;apertura della dichiarazione di implementation. Cos\u00ec facendo, la variabile sar\u00e0 preallocata in memoria dal nostro eseguibile e tutte le classi potranno trarne giovamento.<\/p>\n<p><strong>Nota:<\/strong> I pi\u00f9 attenti di voi avranno notato che non \u00e8 stato assegnato nessun valore alla variabile statica dichiarata. Nonostante questo strano comportamento, l&#8217;applicativo funziona correttamente ed il risultato \u00e8 quello aspettato. Perch\u00e8?<\/p>\n<p>A questo punto, quello che ci resta da fare \u00e8 creare i due metodi di accesso alla propriet\u00e0 dichiarata nel file di interfaccia. I metodi di <strong>set<\/strong> ed i metodi di <strong>get<\/strong> sopra, svolgono il compito richiesto.<\/p>\n<h4>La classe controllore<\/h4>\n<p>Una volta creata la categoria, spostiamo la nostra attenzione sul controllore di vista. Procediamo come da abitudine, creando una classe che eredita direttamente da UIViewController:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-03.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-03.jpg\" alt=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-03\" title=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-03\" width=\"550\" height=\"370\" class=\"aligncenter size-full wp-image-8766\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-03.jpg 726w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-03-300x202.jpg 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>e chiamiamola MainViewController:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-04.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/t107-referenze-associative-aggiungere-variabili-alle-categorie-04.jpg\" alt=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-04\" title=\"t107-referenze-associative-aggiungere-variabili-alle-categorie-04\" width=\"550\" height=\"370\" class=\"aligncenter size-full wp-image-8767\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Modifichiamo il file di interfaccia (.h), aggiungendo una dichiarazione di inclusione per la nuova categoria creata ed aggiungiamo una variabile d&#8217;istanza denominata contentView. In questo modo, potremo dialogare con la categoria appena creata:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import <UIKit\/UIKit.h>\r\n#import \"UIView+TagObject.h\"\r\n@interface MainViewController : UIViewController {\r\nUIView *contentView;\r\n}\r\n@end\r\n<\/pre>\n<p>Spostiamoci sul file di implementazione ed aggiungiamo i metodi di inizializzazione e caricamento programmatico della view principale del controllore:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@implementation MainViewController\r\n- (void)loadView\r\n{\r\ncontentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];\r\n[contentView setBackgroundColor:[UIColor darkGrayColor]];\r\nNSDictionary *aDictionary = [NSDictionary dictionaryWithObject:@\"STOREDVALUE\"\r\n                                                        forKey:@\"aKey\"];\r\n\/\/set the Associative Reference to whatever you want...\r\n[contentView setObjectTag:aDictionary];\r\n...\r\n}\r\n<\/pre>\n<p>Le uniche parti importanti di questo codice, sono quelle relative all&#8217;uso dei metodi setter e getter, creati appositamente per la nostra categoria. Ci baster\u00e0 creare un&#8217;istanza di un NSDictionary ed associarla attraverso il metodo di set alla nuova property della nostra categoria. In questo modo, qualunque parte del codice che ha visibilit\u00e0 su contentView potr\u00e0 accedere al nostro dizionario custom. A tal proposito, scriviamo il metodo responsabile della pressione sull\u2019oggetto UIButton, istanziato in fase di loadView:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)buttonDidPressed:(id)sender {\r\nNSDictionary *aDictionary = [contentView objectTag];\r\n  \/\/ Do something usefull with this object...\r\n  ...\r\n}\r\n<\/pre>\n<p>Modifichiamo, infine, il file di AppDelegate, in maniera che possa caricare correttamente la nostra classe UIViewController, in fase di didFinishLaunching:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import \"AppDelegate.h\"\r\n#import \"MainViewController.h\"\r\n@implementation AppDelegate\r\n...\r\n- (BOOL)application:(UIApplication *)application\r\ndidFinishLaunchingWithOptions:(NSDictionary *)launchOptions\r\n{\r\n  ...\r\nMainViewController *mainVC = [[[MainViewController alloc]\r\n                                                   init] autorelease];\r\n[self.window setRootViewController:mainVC];\r\nself.window.backgroundColor = [UIColor whiteColor];\r\n[self.window makeKeyAndVisible];\r\nreturn YES;\r\n}\r\n<\/pre>\n<p>Compiliamo ed avviamo il nostro progetto. All&#8217;apertura, premendo sul tasto al centro dello schermo, recupereremo il valore di dizionario associato alla contentView, mostrandolo a schermo.<br \/>\nQuesto comportamento \u00e8 possibile grazie all&#8217;uso della categoria UIView che specializza la classe base, aggiungendo la possibilit\u00e0 di &#8220;taggare&#8221; l&#8217;oggetto standard, associandogli un oggetto custom qualsiasi.<\/p>\n<h4>Varianti sul tema e passaggio di parametri ad un selettore<\/h4>\n<p>L&#8217;uso delle referenze associative pu\u00f2 andare ben oltre il nostro primo esempio, dimostrandosi essenziale nell&#8217;utilizzo di particolari pattern di programmazione. Una delle domande che mi viene rivolta pi\u00f9 spesso durante i corsi di programmazione iOS \u00e8 quella di come poter passare dei parametri ad un selettore<br \/>\nassociato, ad esempio, alla pressione di un oggetto UIButton.<br \/>\nRiprendiamo il nostro esempio precedente e supponiamo che il selettore associato all&#8217;oggetto UIButton abbia necessit\u00e0 di ottenere dei valori dinamici in base a particolari stati dell&#8217;applicazione.<\/p>\n<p>Modifichiamo il file di implementazione del MainViewController come segue:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nstatic char UIB_PROPERTY_KEY;\r\n...\r\n@implementation MainViewController\r\n...\r\n- (void)loadView\r\n{\r\n...\r\nobjc_setAssociatedObject(aButton, &UIB_PROPERTY_KEY, aDictionary,\r\nOBJC_ASSOCIATION_RETAIN_NONATOMIC);\r\n...\r\n}\r\n<\/pre>\n<p>Cos\u00ec facendo, abbiamo associato lo stesso dizionario precedentemente legato alla contentView, all&#8217;oggetto UIButton. Questo significa che, all&#8217;invocazione del selettore, avremo modo di leggere questo dizionario. Vediamo come:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)buttonDidPressed:(id)sender {\r\n  ...\r\nNSDictionary *anotherDict = objc_getAssociatedObject(sender,\r\n                                                     &UIB_PROPERTY_KEY);\r\n  ...\r\n}\r\n<\/pre>\n<p>Nota come \u00e8 possibile accedere direttamente all&#8217;oggetto associato, passando come primo parametro il puntatore generico sender, passato al selettore.<\/p>\n<p>A questo punto, il nostro selettore potr\u00e0 reagire in maniera diversa, a seconda dei dati contenuti nel dizionario d&#8217;esempio. Le varianti sul tema e gli scenari di possibile applicazione di questa tecnica diventano infiniti ed &#8220;allegeriscono&#8221; la nostra classe di tante variabili d&#8217;istanza, spesso inutili.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/AssociativeReference.zip\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" 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 progetto presentato, <a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/04\/AssociativeReference.zip\" target=\"_blank\">questo \u00e8 il link per scaricare il nostro esempio.<\/a><\/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\/allertasoglie-tre\/id393552998?mt=8&#038;partnerId=2003\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/12\/banner-allertasoglie-push-tre.jpg\" alt=\"banner-allertasoglie-push-tre\" title=\"banner-allertasoglie-push-tre\" width=\"550\" height=\"293\" class=\"aligncenter size-full wp-image-8150\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/12\/banner-allertasoglie-push-tre.jpg 550w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/12\/banner-allertasoglie-push-tre-300x159.jpg 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\n<\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Una delle caratterestiche pi\u00f9 importanti di Objective-C di cui abbiamo gi\u00e0 parlato in un precedente articolo sono&#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":[1082,1076,203,1079,1080,1078,5,1081,1077,1075],"class_list":["post-8758","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-categorie-objective-c","tag-categories-objective-c","tag-cocoa","tag-cocoatouch","tag-ios-objective-c","tag-nsobject","tag-objective-c","tag-osx-objective-c","tag-references-objective-c","tag-selector-objective-c"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8758","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=8758"}],"version-history":[{"count":14,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8758\/revisions"}],"predecessor-version":[{"id":8777,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8758\/revisions\/8777"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=8758"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=8758"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=8758"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}