{"id":6748,"date":"2011-05-03T14:23:30","date_gmt":"2011-05-03T12:23:30","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=6748"},"modified":"2011-05-04T20:54:29","modified_gmt":"2011-05-04T18:54:29","slug":"t093-utilizziamo-lo-shake-per-ottenere-delle-frasi-casuali","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t093-utilizziamo-lo-shake-per-ottenere-delle-frasi-casuali\/","title":{"rendered":"T#093 &#8211; Utilizziamo lo shake per ottenere delle frasi casuali"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1-159x300.png\" alt=\"\" width=\"80\" height=\"150\" class=\"size-medium alignleft wp-image-6750\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1-159x300.png 159w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1.png 396w\" sizes=\"auto, (max-width: 80px) 100vw, 80px\" \/><\/a> Ciao a tutti, ho pensato di scrivere questo tutorial semplice semplice per venire incontro a tutti gli utenti che ne hanno fatto richiesta sul nostro forum. In particolare creeremo un&#8217;applicazione per iPhone che scuotendo il device, oppure cliccando su un apposito pulsante, mostrer\u00e0 a video una frase random prelevandola da un file plist. Per rendere il tutto pi\u00f9 semplice ho scelto di utilizzare Interface Builder per la realizzazione dell&#8217;interfaccia e di utilizzare gli strumenti messi a disposizione dal nuovo XCode4 per dichiarare le IBaction e IBOutlet. Il risultato finale \u00e8 quello che vedete qui a lato, la foto di sfondo \u00e8 del grande <a href=\"http:\/\/it.wikipedia.org\/wiki\/Maurits_Cornelis_Escher\" target=\"_blank\">Escher<\/a> (click sull&#8217;immagine per ingrandire)<!--more--><\/p>\n<h4>Creiamo e prepariamo il nostro nuovo progetto XCode<\/h4>\n<p>Iniziamo quindi con il creare un nuovo progetto di tipo &#8220;view-based appliation&#8221; e chiamiamolo &#8220;Oracolo di DevAPP&#8221;<\/p>\n<div id=\"attachment_6753\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img2.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6753\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img2-300x203.png\" alt=\"\" width=\"300\" height=\"203\" class=\"size-medium wp-image-6753\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img2-300x203.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img2-150x101.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img2.png 736w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p id=\"caption-attachment-6753\" class=\"wp-caption-text\">Creazione del nuovo progetto<\/p>\n<\/div>\n<p>Occupiamoci quindi del file che conterr\u00e0 le frasi. Come ho avuto modo di dire pi\u00f9 volte in ogni programma ben fatto \u00e8 necessario separare il codice dai dati. Questo per certi aspetti complica un p\u00f2 la prima stesura del programma, infatti molti utenti alle prime armi tendono a fare un p\u00f2 di commistione tra dati e codice, per esempio un approccio errato a questo problema potrebbe essere:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n\/\/r \u00e8 un numero random\r\nif (r == 0) {\r\n    NSLog(@\"ecco la prima frase random\");\r\n}\r\nelse if (r == 1) {\r\n    NSLog(\"ecco la seconda frase random\");\r\n}\r\n\/\/etc etc...\r\n<\/pre>\n<p>Perch\u00e9 sia sbagliato \u00e8 presto detto: supponiamo che la community inizi a suggerirmi delle frasi da aggiungere all&#8217;oracolo&#8230;se avessi utilizzato questo approccio sarei costretto a rivedere il programma ogni volta, trovando il punto dove ad r viene assegnato il numero random, aggiungere un ulteriore blocco &#8220;else if&#8221;&#8230;insomma un sacco di roba che probabilmente potrebbe farmi generare qualche errore.<\/p>\n<p>Utilizziamo piuttosto un approccio differente, aggiungiamo al nostro programma un file plist e chiamiamolo &#8220;elencofrasi.plist&#8221;<\/p>\n<div id=\"attachment_6757\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img3.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6757\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img3-300x204.png\" alt=\"\" width=\"300\" height=\"204\" class=\"size-medium wp-image-6757\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img3-300x204.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img3-150x102.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img3.png 733w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p id=\"caption-attachment-6757\" class=\"wp-caption-text\">Aggiungi un nuovo file plist<\/p>\n<\/div>\n<p>Visualizzate ora il file pslit come &#8220;source code&#8221; facendo un click con il tasto destro sul nome del file, e sostituite il contenuto del file con questo:<\/p>\n<pre lang=\"xml\" line=\"1\" escaped=\"true\">\r\n<?xml version=\"1.0\" encoding=\"UTF\u20138\"?>\r\n<!DOCTYPE plist PUBLIC \"\u2013\/\/Apple\/\/DTD PLIST 1.0\/\/EN\" \"http:\/\/www.apple.com\/DTDs\/PropertyList\u20131.0.dtd\">\r\n<plist version=\"1.0\">\r\n<array>\r\n<string>Ricordati di fare il release degli oggetti allocati<\/string>\r\n<string>Ricordati del metodo dealloc<\/string>\r\n<string>Ricordati di impostare il datasource per le UITableView<\/string>\r\n<string>Ricordati di impostare il delegate per le UITableView<\/string>\r\n<string>Ricordati che esiste un solo sito per lo sviluppo iOS: devapp.it<\/string>\r\n<string>Ricordati che rispondere sul forum \u00e8 una cortesia, non un obbligo<\/string>\r\n<string>Ricordati che le richieste HTTP devono essere fatte su un thread separato<\/string>\r\n<string>Ricordati che se copi il contenuto dei nostri tutorial avrai sette anni di disgrazie<\/string>\r\n<string>Ricordati di condividere le tue conoscenze<\/string>\r\n<string>Ricordati di rigranziare chi ha scritto questo tutorial :) :) <\/string>\r\n<\/array>\r\n<\/plist>\r\n<\/pre>\n<h4>La logica del programma<\/h4>\n<p>La logica del programma \u00e8 abbastanza semplice, vogliamo che all&#8217;apertura vengano caricate le frasi leggendole da un file plist e successivamente, scuotendo il device oppure cliccando su un pulsante, venga visualizzata una frase random.<\/p>\n<p>Dichiariamo quindi nel file Oracolo_di_DevAPPViewController un NSArray e un intero<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n\tNSArray *elencoFrasi;\r\n\tint fraseCorrente;\r\n<\/pre>\n<p>Non utilizzer\u00f2 @property perch\u00e9 non servono in questo momento.<br \/>\nInizializzo queste variabili all&#8217;interno del metodo <em>viewDidLoad<\/em>, in altri casi potrebbe essere necessario inizializzarle in altri momenti, ma in questo esempio va bene questo metodo.<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)viewDidLoad\r\n{\r\n    [super viewDidLoad];\r\n\tNSString *filePath = [[NSBundle mainBundle] pathForResource:@\"elencoFrasi\" ofType:@\"plist\"];\r\n\telencoFrasi = [[NSArray alloc] initWithContentsOfFile:filePath];\r\n\tsrand (time(NULL));\r\n\tfraseCorrente = -1;\r\n}\r\n<\/pre>\n<p>Le prime due istruzioni servono ad inizializzare la variabile &#8220;elencoFrasi&#8221; con il contenuto del file plist, attenzione ho scritto &#8220;alloc&#8221; quindi ricordiamo di farne il release nel metodo dealloc del viewcontroller.<\/p>\n<p>L&#8217;istruzione:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nsrand (time(NULL));\r\n<\/pre>\n<p>permette invece di impostare il seme per il generatore di numeri pseudo-random.<\/p>\n<p>Questo argomento necessiterebbe di un intero libro, ma per il momento ci basta sapere che la funzione <em>rand()<\/em> che utilizzeremo tra breve non genera dei numeri realmente casuali, ma dei numeri definiti pseudo-random, la successione di questi numeri \u00e8 stabilita da un parametro numerico, detto &#8220;seme&#8221; e la funzione <em>srand()<\/em> \u00e8 la funzione che serve per impostare questo seme, gli passiamo come parametro il numero di secondi intercorsi dalla mezzanotte del 1 gennaio 1970 (l&#8217;origine dello <a href=\"http:\/\/en.wikipedia.org\/wiki\/Unix_time\" target=\"_blank\">standard unix time<\/a> ) in questo modo siamo <em>ragionevolmente<\/em> sicuri che ad ogni esecuzione del nostro programma il seme verr\u00e0 inizializzato ad un valore diverso.<\/p>\n<h4>Riconoscere lo shake del device<\/h4>\n<p>Per riconoscere l&#8217;avvenuto shake del device possiamo, per evitare di analizzare i dati dell&#8217;accelerometro, inserire questo codice all&#8217;interno del viewcontroller:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n-(BOOL)canBecomeFirstResponder {\r\n    return YES;\r\n}\r\n\r\n-(void)viewDidAppear:(BOOL)animated {\r\n    [super viewDidAppear:animated];\r\n    [self becomeFirstResponder];\r\n}\r\n\r\n- (void)viewWillDisappear:(BOOL)animated {\r\n    [self resignFirstResponder];\r\n    [super viewWillDisappear:animated];\r\n}\r\n\r\n- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event\r\n{\r\n    if (motion == UIEventSubtypeMotionShake)\r\n    {\r\n\t\t[self showNextAdvice:nil];\r\n    }\r\n}\r\n<\/pre>\n<p>Spiegare in dettaglio cosa facciano questi metodi ci porterebbe un p\u00f2 fuori tema, diciamo brevemente che ci assicuriamo che il nostro viewController sia, quando visibile, il <em>FirstResponder<\/em> al quale inviare il messaggio dell&#8217;avvenuto shake. Nell&#8217;ultimo metodo richiamo espressamente il metodo &#8220;showNextAdvice:nil&#8221; per visualizzare una nuova frase.<br \/>\n<strong>Attenzione:<\/strong> il metodo &#8220;showNextAdvice&#8221; ancora non \u00e8 stato dichiarato, continuate a leggere prima di compilare.<\/p>\n<h4>L&#8217;interfaccia grafica<\/h4>\n<p>Salviamo il tutto e iniziamo ad occuparci dell&#8217;interfaccia.<br \/>\nSelzioniamo il file &#8220;Oracolo_di_DevAPPViewController.xib&#8221; e XCode4 visualizzer\u00e0 tutti i controlli necessari per disegnare la nostra interfaccia.<\/p>\n<p>Io ho aggiunto:<\/p>\n<ol>\n<li>Una UIImageView per lo sfondo<\/li>\n<li>Una UIImageView per ospitare il logo di devAPP<\/li>\n<li>Una UITextView per ospitare la frase<\/li>\n<li>Un UIButton per richiedere una nuova frase<\/li>\n<\/ol>\n<p>La UITextView \u00e8 stata impostata con uno sfondo trasparente, cos\u00ec da poter visualizzare lo sfondo.<br \/>\nAbbiamo bisogno quindi di un IBOutlet che colleghi la UITextView che abbiamo inserito e una IBAction che colleghi l&#8217;UIButton ad un metodo della nostra classe. Utilizziamo quindi le nuove features di XCode 4, visualizziamo l&#8217;assistant editor cliccando sul pulsante dedicato:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img4-300x76.png\" alt=\"\" width=\"300\" height=\"76\" class=\"aligncenter size-medium wp-image-6766\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img4-300x76.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img4-150x38.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img4.png 313w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>L&#8217;assistant editor visualizzer\u00e0 il file .h corrispondente all&#8217;interfaccia visualizzata, quindi possiamo trascinare (sempre con il tasto dx) dall&#8217;interfaccia sul codice sorgente per far apparire il men\u00f9 che ci permette di creare automaticamente gli IBAction e IBOutlet di cui abbiamo bisogno:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img5-150x150.png\" alt=\"\" width=\"150\" height=\"150\" class=\"aligncenter size-thumbnail wp-image-6769\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img5-150x150.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img5-92x92.png 92w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img5-64x64.png 64w\" sizes=\"auto, (max-width: 150px) 100vw, 150px\" \/><\/a><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img6-150x150.png\" alt=\"\" width=\"150\" height=\"150\" class=\"aligncenter size-thumbnail wp-image-6770\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img6-150x150.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img6-92x92.png 92w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img6-64x64.png 64w\" sizes=\"auto, (max-width: 150px) 100vw, 150px\" \/><\/a><br \/>\n<\/center><\/p>\n<p><strong>Una piccola nota:<\/strong> l&#8217;idea di creare un metodo il cui unico compito \u00e8 quello di visualizzare una nuova frase non \u00e8 casuale ma ci permetter\u00e0 di riciclare il codice scritto all&#8217;interno di questo metodo in pi\u00f9 parti del programma, in questo esempio lo stesso metodo verr\u00e0 richiamato sia dal &#8220;touch up inside&#8221; del pulsante sia con lo shake del device. In alcuni casi ho visto scrivere tutta la logica del programma all&#8217;interno del metodo richiamato dall&#8217;accelerometro, non \u00e8 un approccio corretto, perch\u00e9 in quel caso se vogliamo eseguire la stessa azione scatenata per\u00f2 da un evento diverso siamo costretti a fare copia-incolla del codice.<\/p>\n<h4>Il metodo showNextAdvice <\/h4>\n<p>Adesso il passo finale, inseriamo il contenuto del metodo showNexAdvice.<\/p>\n<p>Il mio codice \u00e8 questo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (IBAction)showNextAdvice:(id)sender {\r\n\tint r;\r\n\tint maxIndex = [elencoFrasi count] - 1;\r\n\tif (fraseCorrente == -1) {\r\n\t\tr = rand() % maxIndex;\r\n\t}\r\n\telse {\r\n\t\tr = rand() % (maxIndex - 1);\r\n\t\tif (r == fraseCorrente) {\r\n\t\t\tr = maxIndex;\r\n\t\t}\r\n\t\t\r\n\t}\t\r\n\tfraseCorrente = r;\r\n\t[textArea setText:[elencoFrasi objectAtIndex:r]];\r\n}\r\n<\/pre>\n<p>Pu\u00f2 sembrare farraginoso, ma vi assicuro che c&#8217;\u00e8 un perch\u00e9.<br \/>\nPer iniziare dichiaro due variabili, <em>r<\/em> e <em>maxIndex<\/em>, la prima conterr\u00e0 il numero random generato, la seconda invece ci servir\u00e0 per evitare di generare numeri pi\u00f9 grandi dell&#8217;ultima posizione dell&#8217;array, infatti \u00e8 inizializzata a:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n[elencoFrasi count] - 1;\r\n<\/pre>\n<p>Eseguo poi un test per verificare se &#8220;frasecorrente == -1&#8221;, questa condizione pu\u00f2 essere verificata solo all&#8217;avvio del programma, perch\u00e9 poi ad ogni frase scelta la variabile frasecorrente non potr\u00e0 mai essere -1.<br \/>\nQuindi visto che \u00e8 stiamo per visualizzare la nostra prima frase scegliamo tranquillamente un numero random tra 0 ed il massimo indice possibile e visualizziamo la frase nella textview.<br \/>\nE se il test precedente restituisce falso? Allora vuol dire che abbiamo gi\u00e0 estratto qualche numero random, e mi sono preso la briga di evitare che un numero possa essere estratto due volte di seguito.<br \/>\nQualcuno potrebbe dire &#8220;basta verificare che sia diverso dal precedente, se non lo \u00e8 ne rigeneri un altro&#8221;&#8230;purtroppo non \u00e8 una risposta corretta perch\u00e9 in linea di principio questo tipo di approccio potrebbe portare ad un loop infinito, adottiamo quindi una soluzione pi\u00f9 adatta. Se l&#8217;array \u00e8 composto da <em>n<\/em> frasi, dobbiamo garantire alle <em>n-1<\/em> frasi restanti la stessa probabilit\u00e0 di uscita, quindi dobbiamo estrarre un numero non pi\u00f9 da 0 a <em>n-1<\/em> ma da 0 a <em>n-2<\/em> (non confondiamoci con gli indici per carit\u00e0!) cos\u00ec facendo, per\u00f2, avremmo rimesso nel mucchio anche il precedente estratto ed escluso quello in posizione n-1, basta quindi fare un controllo, se ho estratto lo stesso numero di prima allora restituisco quello in posizione n-1. <\/p>\n<p>Se non fossero bastate le mie parole a confondervi le idee eccovi un&#8217;immagine che vi chiarir\u00e0 maggiormente le idee:<\/p>\n<div id=\"attachment_6784\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6784\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap-300x183.png\" alt=\"\" width=\"300\" height=\"183\" class=\"size-medium wp-image-6784\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap-300x183.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap-1024x627.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap-150x91.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_imgSwap.png 1054w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p id=\"caption-attachment-6784\" class=\"wp-caption-text\">La scelta certa di due random differenti.<\/p>\n<\/div>\n<p>A questo punto il programma \u00e8 terminato, non mi resta che augurarvi buon coding.<br \/>\nAlla prossima<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/05\/Oracolo_di_devAPP.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 tutorial,\u00a0<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/05\/Oracolo_di_devAPP.zip\" target=\"_blank\">questo \u00e8 il nostro file di progetto (per XCode 4).<\/a><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1-159x300.png\" alt=\"\" width=\"159\" height=\"300\" class=\"size-medium aligncenter wp-image-6750\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1-159x300.png 159w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1-79x150.png 79w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2011\/04\/shaketutorial_img1.png 396w\" sizes=\"auto, (max-width: 159px) 100vw, 159px\" \/><\/a><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/supporto-applicazioni\/le-applicazioni-dei-nostri-autori\/parole-vietate-di-ignazio-calo\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/02\/bannerIgnazioc.png\" alt=\"\" width=\"480\" height=\"100\" \/><\/a><br \/>\n<\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ciao a tutti, ho pensato di scrivere questo tutorial semplice semplice per venire incontro a tutti gli&#8230;<\/p>\n","protected":false},"author":53,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[736,735,241,413,734,242],"class_list":["post-6748","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-esempi-codice-programmazione-iphone","tag-frasi-a-random-iphone-app","tag-ignazio-calo","tag-programmare-iphone","tag-shake-iphone","tag-tutorial-xcode"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/6748","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\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=6748"}],"version-history":[{"count":46,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/6748\/revisions"}],"predecessor-version":[{"id":6788,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/6748\/revisions\/6788"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=6748"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=6748"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=6748"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}