Abbonati al feed RSS!
twitter
  •  

DevTutorial #21 – Creiamo il nostro client per Twitter! (Parte 1)

|
Categorie: DevTutorial

10

Dopo una lunga attesa, eccoci con una nuova serie di tutorial!

Quello che inizieremo a realizzare oggi (e per un altro paio di tutorial successivi) sarà un nostro personalissimo client per Twitter! Vedremo, infatti, come sfruttare il progetto MGTwitterEngine, che ci permetterà di interagire con il nostro account di Twitter. Utilizzeremo, inoltre, degli aspetti più particolari e complessi dell’iPhone SDK.

Ecco quello che faremo oggi:

  • Inserire la libreria MGTwitterEngine nel nostro progetto e settarla in maniera corretta;
  • Collegarci, sfruttando tale libreria, alla nostro timeline di Twitter;
  • Ricavare i vari tweet della timeline e salvarli in una lista con elemento ad-hoc.

Già che siamo in tema, vi ricordo che il nostro canale Twitter è raggiungibile a questo indirizzo, vi invito a seguirci se ancora non lo fate! ;-)

Ora sotto con il codice, buon tutorial a tutti!

1) Creiamo il progetto e settiamo la libreria “MGTwitterEngine”

Iniziamo creando un nuovo progetto di tipo “View-based application” e chiamiamolo “SampleTwitterClient”.

Schermata 2009-12-28 a 22.11.24

Prima di fare qualsiasi altra cosa, inseriamo la libreria MGTwitterEngine, che ci permetterà di interagire con Twitter. Scaricate l’ultima versione da questa repository SVN (trovate qui una guida su come fare), oppure scarica la versione 1.08 che vi mettiamo noi a disposizione.

Estraiamo l’archivio ed apriamo il file “MGTwitterEngine.xcodeproj”, un progetto esempio che potete guardare per avere una panoramica della libreria.La procedura che dovete eseguire è spiegata nel file “README.txt” di questo progetto, ma vi illustrerò tutti i passaggi in modo che non abbiate problemi di alcun genere.

A noi interessa la cartella “MGTwitterEngine” che trovate all’interno di “Classes”:

Schermata 2009-12-28 a 22.17.27

Prendetela e trascinatela all’interno del nostro progetto “SimpleTwitterClient” che abbiamo creato poco fa:

README.txt - MGTwitterEngine

e cliccate su “Add” nella schermata che vi apparirà appena rilascerete la cartella, ricordandovi di mettere il segno di spunta nell’opzione in alto.

Schermata 2009-12-28 a 22.18.42

Possiamo chiudere il progetto “MGTwitterEngine” e tornare al nostro “SampleTwitterClient”. Importiamo, ora, il framework che si dovrà occupare del parsing XML. Clicchiamo con il tasto destro sulla cartella “Frameworks” e scegliamo “Add” -> “Existing Frameworks…”:

Schermata 2009-12-28 a 22.23.41

Dall’elenco che appare selezioniamo poi “libxml2.dylib” e clicchiamo su “Add”.

Schermata 2009-12-28 a 22.24.24

Abbiamo così importato il framework necessario.

Ci manca solo un’operazione per fare in modo che la libreria “MGTwitterEngine” funzionioni alla perfezione. Facciamo doppio clic sul nome del progetto per aprirne le proprietà. Nella sezione “Build” cerchiamo la voce “Header Search Path”:

Schermata 2009-12-28 a 22.26.38

facciamoci doppio clic e quando si apre inseriamoci la stringa “$SDKROOT/usr/include/libxml2″ (ci basterà cliccare sul bottoncino “+”):

Schermata 2009-12-28 a 22.27.30

Abbiamo concluso la fase iniziale di creazione del nostro progetto.

2.Definiamo la vista di caricamento

XCode ha già creato per noi una vista, “SampleTwitterClientViewController.xib”. Questa verrà caricata al’avvio dell’applicazione, sarà qui che andremo a leggere la nostra timeline di Twitter. Prima di fare ciò, creiamo un semplice aspetto grafico per questa vista.

Aprite il file “SampleTwitterClientViewController.xib” e modificatelo a vostro piacere. Io l’ho modificato così:

Schermata 2009-12-28 a 22.36.19

Come vedete al centro ho inserito un componente “UIActivityIndicatorView”, che utilizzeremo per far capire all’utente che l’applicazione sta caricando i dati e non è bloccata.

Salvate il file e chiudete pure Interface Builder.

3. Creiamo la classe “Tweet”

Come abbiamo già detto, la nostra applicazione andrà a leggere la timeline del nostro account di Twitter. Dobbiamo creare una classe, quindi, in grado di ospitare le informazioni di ogni singolo tweet letto. Per semplicità, ci limiteremo a salvare solo alcuni dati di ogni tweet: nome dell’utente che ha “cinguettato”, la sua immagine del profilo e il testo del tweet.

Facciamo clic con il tasto destro su “Classes” e clicchiamo poi su “Add” -> “New File…”. Creiamo, poi, una classe del tipo “Objective-C class”, e chiamiamola “Tweet”.

Vediamo di definire le variabili e i metodi di questa classe.

Nel file “Tweet.h” inseriamo il seguente codice:

1
2
3
4
5
6
7
8
9
10
11
#import <Foundation/Foundation.h>
 
@interface Tweet : NSObject {
 NSString *testo;
 NSString *user;
 UIImage *immagine;
}
 
@property (nonatomic, retain) NSString *testo;
@property (nonatomic, retain) NSString *user;
@property (nonatomic, retain) UIImage *immagine;

Abbiamo dichiarato tre elementi, come detto poco fa:

  • testo, conterrà il messaggio del tweet, il testo;
  • user, conterrà l’username di chi ha inserito il tweet letto;
  • immagine, è l’immmagine (l’avatar) dell’utente che ha lasciato il tweet.

Niente di complicato quindi. Nel file “Tweet.m” dovrete solo implementare il metodo “dealloc” e inserire “@synthesize”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import "Tweet.h"
 
@implementation Tweet
 
@synthesize testo, user, immagine;
 
-(void)dealloc{
 [testo release];
 [user release];
 [immagine release];
 [super dealloc];
}
 
@end

Ovviamente se intendete creare un client più complesso potrete aumentare i componenti di questa classe, ma per questo tutorial ci basteranno questi elementi.

4. Definiamo la classe “SampleTwitterClientViewController.h”

È venuto finalmente il momento di implementare la classe che si occuperà di leggere la timeline di Twitter.

Apriamo il file “SampleTwitterClientViewController.h” e inseriamo il seguente codice

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import <UIKit/UIKit.h>
#import "MGTwitterEngine.h"
 
@class Tweet;
 
@interface SampleTwitterClientViewController : UIViewController <MGTwitterEngineDelegate> {
 MGTwitterEngine *twitterEngine;
 NSMutableArray *listaTweet;
 IBOutlet UIActivityIndicatorView *spinner;
}
 
-(NSString*)getMessaggio:(NSString*)element;
-(NSString*)getUser:(NSString*)element;
-(NSURL*)getUrlImage:(NSString*)element;
 
@property (nonatomic, retain) NSMutableArray *listaTweet;
@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *spinner;
 
@end

Alla riga 7 abbiamo definito un elemento di tipo “MGTwitterEngine”, proprio quello della classe che abbiamo inserito all’inizio del tutorial. Sarà questo componente che si occuperà della connessione con Twitter e della lettura della nostra timeline. Nell’intestazione (riga 6) abbiamo anche inserito il protocollo di questa classe, che ci “obbliga” così ad implementare dei metodi che vedremo in seguito.

L’array dichiarato alla riga 8 conterrà vari elementi del tipo “Tweet”, ognuno dei quali conterrà un tweet letto dal nostro account. Sarà, quindi, una lista che conterrà tutti i tweet della nostra timeline.
La riga 9, invece, contiene la definizione della “spinning wheel”, ovvero la classica “rotella che gira”, l’UIActivityIndicatorView che abbiamo inserito in precedenza nella vista (e che collegheremo fra poco in IB).

Ci sono poi 3 metodi getter (“getMessaggio”, “getUser” e “getUrlImage”) che avranno il compito di ricavare il campo desiderato (vedremo infatti che ci verrà restituita una lunga serie di informazioni, da cui dovremo ricavare i valore che ci interessano).

Salviamo la classe e prima di continuare l’implementazione, apriamo nuovamente il file “SampleTwitterClientViewController.xib”, in cui dovremo collegare l’elemento “UIActivityIndicatorView” che abbiamo inserito con quello appena dichiarato nella classe.

Clicchiamo sul “File’s Owner” e andiamo poi nel “Connections Inspector”. Colleghiamo l’elemento “spinner” con il componente grafico che abbiamo già inserito. Se abbiamo eseguito tutto correttamente avrete il seguente risultato:

Schermata 2009-12-28 a 23.06.33

Possiamo salvare e chiudere Interface Builder.

5. Leggiamo i tweet dalla nostra timeline

Iniziamo ad implementare il codice che deve leggere i tweet dalla nostra timeline. Apriamo il file “SampleTwitterClientViewController.m” ed inseriamo il seguente codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#import "SampleTwitterClientViewController.h"
#import "Tweet.h"
 
@implementation SampleTwitterClientViewController
 
@synthesize listaTweet, spinner;
 
-(void)viewDidLoad{
 
 // Qui vanno dichiarati username e password per accedere a Twitter
 NSString *username = @"nome_utente";
 NSString *password = @"password";
 
 // Create a TwitterEngine and set our login details.
 twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];
 [twitterEngine setUsername:username password:password];
 
 // Get updates from people the authenticated user follows.
 [twitterEngine getFollowedTimelineFor:username since:nil startingAtPage:0];
 
 [spinner startAnimating];
}

Non preoccupatevi troppo di capire il codice, in quanto l’ho preso direttamente dall’esempio fornito con la classe “MGTwitterEngine”. Ricordatevi, comunque, di inserire i vostro dati per il login alla riga 11 e 12.
Alla riga 21 abbiamo, inoltre, avviato la rotella (che fermeremo quando la procedura di lettura e conversione dei dati sarà terminata).

Inseriamo, ora, dei metodi obbligatori da inserire, in quanto parte del delegato “MGTwitterEngineDelegate”. Eccoli:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- (void)requestSucceeded:(NSString *)requestIdentifier{
 NSLog(@"Request succeeded (%@)", requestIdentifier);
}
 
- (void)requestFailed:(NSString *)requestIdentifier withError:(NSError *)error{
 NSLog(@"Twitter request failed! (%@) Error: %@ (%@)",
 requestIdentifier,
 [error localizedDescription],
 [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
 [spinner stopAnimating];
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Errore!" message:@"Connessione non riuscita.\nControlla i dati d'accesso" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
 [alert show];
 [alert release];
}
 
- (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)identifier{
 NSLog(@"Got direct messages:\r%@", messages);
}
 
- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)identifier{
 NSLog(@"Got user info:\r%@", userInfo);
}
 
- (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString *)identifier{
 NSLog(@"Got misc info:\r%@", miscInfo);
}

L’unico metodo a cui ho aggiunto un po’ di codice è il secondo, ovvero “requestFailed: withError:”. Questo metodo è avviato se la connessione con Twitter non è possibile, quindi avviamo una UIAlertView che lo comunica all’utente e fermiamo la rotella. Come messaggio comunichiamo che i dati d’accesso sono errati, in realtà dovremmo controllare il codice d’errore e inserire un messaggio a seconda dell’errore riscontrato (potrebbe non esserci la connessione, oppure Twitter potrebbe essere down, o i dati inseriti potrebbero essere errati, etc).

Mancano solo pochi metodi per concludere questo primo tutorial. Ecco cosa dovete inserire ora:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)identifier{
 
 listaTweet = [[NSMutableArray alloc] init];
 Tweet *elemento;
 
 for (int i=0; i<statuses.count ; i++) {
 elemento =  [[Tweet alloc] init];
 elemento.testo = [self getMessaggio:[statuses objectAtIndex:i]];
 elemento.user = [self getUser:[statuses objectAtIndex:i]];
 elemento.immagine = [[UIImage imageWithData:[NSData dataWithContentsOfURL:[self getUrlImage:[statuses objectAtIndex:i]]]]retain];
 [listaTweet addObject:elemento];
 }
 [elemento release];
 
 [spinner stopAnimating];
}
 
-(NSString*)getMessaggio:(NSString*)element{
 
 NSString *stringa = [[NSString alloc] initWithFormat:@"%@",element];
 NSArray *parti1 = [stringa componentsSeparatedByString:@"text ="];
 NSArray *parti2 = [[parti1 objectAtIndex:1] componentsSeparatedByString:@"\""];
 
// il codice di seguito ripulisce il nome da eventuali apici presenti
 NSString *nome = [parti2 objectAtIndex:0];
 if ([nome characterAtIndex:0] == '"') {
 return [nome substringWithRange:NSMakeRange(1,nome.length-2)];
 }else {
 return nome;
 }
}
 
-(NSString*)getUser:(NSString*)element{
 
 NSString *stringa = [[NSString alloc] initWithFormat:@"%@",element];
 NSArray *parti1 = [stringa componentsSeparatedByString:@"name = "];
 NSArray *parti2 = [[parti1 objectAtIndex:1] componentsSeparatedByString:@";"];
 
 return [parti2 objectAtIndex:0] ;
}
 
-(NSURL*)getUrlImage:(NSString*)element{
 
 NSString *stringa = [[NSString alloc] initWithFormat:@"%@",element];
 NSArray *parti1 = [stringa componentsSeparatedByString:@"\"profile_image_url\" ="];
 NSArray *parti2 = [[parti1 objectAtIndex:1] componentsSeparatedByString:@"\""];
 
 return [NSURL URLWithString:[parti2 objectAtIndex:1]];
}

Questa è sicuramente la parte più importante. Il metodo “statusesReceived” viene richiamato quando è stata letta la timeline di Twitter del vostro account. Nell’array “statuses”, infatti, sono presenti tutti i tweet letti con tutti gli elementi relativi ad ogni singolo tweet (testo, username di chi lo ha lasciato, posizione della “geolocalizzazione”, url dell’immagine del profilo, etc). Se volete visualizzarne il contenuto vi basterà usare l’istruzione NSLog(@”%@”,statuses);.

Il codice presente nel metodo appena descritto si occupa di leggere ogni tweet e di ricavarne le informazioni del tweet che ci servono (testo, username e immagine). I tre metodi “getXXX” hanno proprio il compito di ricavare l’informazione (se volete leggere nuovi campi dovrete creare un metodo “get” personalizzandolo in base alle vostre necessità).

Quello che potrebbe sembrarvi più complicato è la lettura dell’immagine. Il metodo “getUrlImage” ci restituisce un elemento NSURL, che è l’indirizzo web dell’immagine dell’utente. Alla riga 10 creiamo, poi, un’immagine a partire dai dati letti a quell’indirizzo (XCode ci restituisce infatti una NSData, che va convertita in UIImage). L’immagine convertita viene poi inserita nell’elemento corrente (ovviamente nel campo “immagine”).

Alla fine del ciclo for avremo la “listaTweet” che conterrà n elementi di tipo Tweet, ognuno dei quali avrà le informazioni ricavate in precedenza. Proprio ciò che volevamo.

Abbiamo così completato questa prima parte del tutorial!

Se volete controllare che abbiate letto i valori della vostra timeline utilizzate questo ciclo alla fine del metodo “statusesReceived”

1
2
3
4
for (int j=0; j<[listaTweet count]; j++) {
 Tweet *elemento = [listaTweet objectAtIndex:j];
 NSLog(@"testo: %@, user: %@, url: %@",elemento.testo,elemento.user,elemento.urlImgUser);
 }

e leggete i risultati nella Console di debug.

Schermata 2009-12-29 a 00.14.16

Nel prossimo tutorial vedremo come creare una tabella personalizzata in cui inserire gli elementi che abbiamo letto.

Se Avete Problemi, questo è il nostro file di progetto.

La guida è stata creata da Andrea Busi per “Bubi Devs”.
I meriti, quindi, sono del legittimo autore.

462 visite

Commenti (10)

Reply to this comment

Wow!Oggi provo questa mitica guida

Reply to this comment

tutorial fantastico!!

Reply to this comment

Non ho letto tutto il tutorial, ma mi sono fermato alla classe Tweet, dove mi sembra che ci siano un paio di errori.
Nel metodo dealloc, infatti, imposti le due variabili di istanza, testo e user, a nil, ma senza rilasciarle.
Dato che quando vengono impostate viene fatto un retain, quando non servono più vanno rilasciate, altrimenti si creeranno dei memory leak.
Allo stesso modo, anche la variabile immagine andrebbe rilasciata, invece gli viene passato il metodo dealloc, che, come spiegato dalla documentazione, non andrebbe mai chiamato direttamente.
Impostare le variabili a nil, poi, non a senso nel metodo dealloc, dato che questo viene chiamato quando l’oggetto viene distrutto, quindi non c’è più il rischio di usare quelle variabili.
Andrebbe, invece, bene farlo in altri metodi della classe, dopo aver rilasciato l’oggetto, si può impostare il puntatore a nil, così che un eventuale uso non aspettato della variabile non punterebbe ad una zona di memoria non più valida causando crash.
La versione corretta sarebbe probabilmente una cosa simile:
- (void)dealloc{
[testo release];
[user release];
[immagine release];
[super dealloc];
}

P.S. Sperando di aver fatto cosa gradita. ;)

Reply to this comment

@MacMomo: ciao, grazie mille della precisazione!

hai perfettamente ragione, ho provveduto subito a correggerle..

ho sbagliato perchè ho preso spunto da una classe che avevo già creato in precedenza, molto simile. In quel caso, però, avevo dichiarato le “property” come copy, quindi in quel caso sarebbe giusto utilizzare il “nil” per rilasciarle..

utilizzando, però, retain per le variabili, è giusto utilizzare poi retain nel metodo dealloc.

grazie ancora della segnalazione, se noti altri errori fammelo sapere! ;-)

Reply to this comment

@Andrea Busi:
Probabilmente l’hai corretto troppo di fretta, perché hai scritto retain invece di release. ;)
(Il metodo retain aumenta il retainCount dell’oggetto, evitando che lo stesso venga rilasciato, mentre il metodo release lo decrementa, permettendo appunto che vanga rilasciata la sua memoria quando questo arriva a 0).

Reply to this comment

@MacMomo: davvero, ma che tonto! xD

ho fatto tutto troppo di fretta.. adesso dovrebbe essere giusto, grazie ancora della segnalazione ;-)

P.S: vedo che te ne intendi di ObjC, se ti va di scrivere qualche tutorial fammi sapere ;-)

Reply to this comment

Andrea busi : So USAre molto bene Gamesalad se vuoi ti scrivo un tutorial!

Reply to this comment

Ciao Andrea,
A quando la nuova parte del tutorial? Non vedo l’ora :D

Grazie,
Matteo

Reply to this comment

[...] prima parte di questo tutorial abbiamo visto come aggiungere la libreria MGTwitterEngine e come leggere la [...]

Reply to this comment

[...] DevTutorial dedicato alla realizzazione di un semplice client per Twitter. Vi ricordo che trovate qui la prima parte, metre qui la [...]

Scrivi un commento!