• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

T#067 – Caricare immagini nelle tabelle in modalità asincrona

By sarnieri | on 30 Luglio 2010 | 7 Comments
Senza categoria

Salve a tutti, dopo una lunghissima pausa torno a scrivere qualche mini tutorial, spero abbiate seguito i miei articoli su piattaforma Bada nel frattempo! Oggi vorrei proporvi la risoluzione di un annoso problema riguardante il caricamento asyncrono di immagini all’interno delle tabelle.

Come sicuramente saprete, è relativamente semplice in Xcode visualizzare un’immagine prendendo il link direttamente via HTTP, ma il caricamente delle righe delle table richiede che vengano scaricate le immagini che visualizziamo PRIMA di visualizzare la riga stessa. L’obiettivo che volevo raggiungere era lo stesso che potete vedere sfogliando l’applicazione ‘App Store’ nella sezione categoria su iPhone/iPod/iPad… in cui se ci fate caso, vedrete apparire immediatamente i testi e poco dopo le 5 icone che vengono scaricate in background asincronicamente (gran parola!).

Innanzitutto creaiamo la classe “AsyncImageView” che richiameremo dal nosto metodo “cellForRowAtIndexPath”.

Di seguito il file AsyncImageView.h

#import 

@interface AsyncImageView : UIView {
    //could instead be a subclass of UIImageView instead of UIView, depending on what other features you want to 
    // to build into this class?
    
    NSURLConnection* connection; //keep a reference to the connection so we can cancel download in dealloc
    NSMutableData* data; //keep reference to the data so we can collect it as it downloads
    //but where is the UIImage reference? We keep it in self.subviews - no need to re-code what we have in the parent class
    
}

- (void)loadImageFromURL:(NSURL*)url;
- (UIImage*) image;

@end

Ed il relativo file di implementazione:

#import "AsyncImageView.h"
 
 
@implementation AsyncImageView
 
- (void)dealloc {
	[connection cancel]; //in case the URL is still downloading
	[connection release];
	[data release]; 
    [super dealloc];
}
 
 
- (void)loadImageFromURL:(NSURL*)url {
	if (connection!=nil) { [connection release]; } //in case we are downloading a 2nd image
	if (data!=nil) { [data release]; }
 
	NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
	connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; //notice how delegate set to self object
}
 
 
//the URL connection calls this repeatedly as data arrives
- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData {
	if (data==nil) { data = [[NSMutableData alloc] initWithCapacity:2048]; } 
	[data appendData:incrementalData];
}
 
//the URL connection calls this once all the data has downloaded
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
	//so self data now has the complete image 
	[connection release];
	connection=nil;
	if ([[self subviews] count]>0) {
		//then this must be another image, the old one is still in subviews
		[[[self subviews] objectAtIndex:0] removeFromSuperview]; //so remove it (releases it also)
	}
 
	//make an image view for the image
	UIImageView* imageView = [[[UIImageView alloc] initWithImage:[UIImage imageWithData:data]] autorelease];
	//make sizing choices based on your needs, experiment with these. maybe not all the calls below are needed.
	imageView.contentMode = UIViewContentModeScaleAspectFit;
	imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight );
	[self addSubview:imageView];
	imageView.frame = self.bounds;
	[imageView setNeedsLayout];
	[self setNeedsLayout];
 
	[data release]; //don't need this any more, its in the UIImageView now
	data=nil;
}
 
- (UIImage*) image {
	UIImageView* iv = [[self subviews] objectAtIndex:0];
	return [iv image];
}
 
@end

Una volta che abbiamo la classe pronta, basterà copiarla dentro a qualsiasi progetto per poterla utilizzare, vediamo come.

Vi riporto per completezza tutto il metodo “cellForRowAtIndexPath”, che come saprete si occupa di valorizzare la riga che stiamo caricando in quel momento.

- (UITableViewCell *)tableView:(UITableView *)tableView
		 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"ImageCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
    if (cell == nil) {
		[[NSBundle mainBundle] loadNibNamed:@"CellaRiepilogo"  owner:self options:NULL];
		cell = nibLoadedCell;
 
    } else {
		AsyncImageView* oldImage = (AsyncImageView*)
		[cell.contentView viewWithTag:999];
		[oldImage removeFromSuperview];
    }
 
	CGRect frame;
	frame.size.width=47; frame.size.height=47;
	frame.origin.x=8; frame.origin.y=8;
	AsyncImageView* asyncImage = [[[AsyncImageView alloc]
								   initWithFrame:frame] autorelease];
	UIImage *myImage = [UIImage imageNamed:@"blackaccessorybutton.png"];
	UIImageView *imageView = [[UIImageView alloc] initWithImage:myImage];
	[cell setAccessoryView:imageView];
 
 
	Sciopero *sciopero = [dati objectAtIndex:indexPath.row];
 
	UILabel		*dataLabel	= (UILabel *)[cell viewWithTag:1];
	UILabel		*settoreLabel= (UILabel *)[cell viewWithTag:2];
	UILabel		*modalitaLabel= (UILabel *)[cell viewWithTag:3];
	UILabel		*descrizioneLabel= (UILabel *)[cell viewWithTag:4];
 
 
	dataLabel.text = [NSString stringWithFormat:@"%@", [sciopero.data uppercaseString]];
	settoreLabel.text = [NSString stringWithFormat:@"%@", sciopero.settore];
	modalitaLabel.text = [NSString stringWithFormat:@"%@", [sciopero.modalita lowercaseString]];
	descrizioneLabel.text = [NSString stringWithFormat:@"%@", [sciopero.descrizione lowercaseString]];
 
 
	asyncImage.tag = 999;
	NSURL *url = [NSURL URLWithString: sciopero.icona];	
	//UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
	//categoria.immagine  = img;
 
	[asyncImage loadImageFromURL:url];
 
	[cell.contentView addSubview:asyncImage];
 
    return cell;
}

Nel mio caso utilizzo una cella personalizzata con uno XIB associato di nome “CellaRiepilogo.xib”.

La parte da personalizzare a seconda dei casi è la seguente:

CGRect frame;
	frame.size.width=47; frame.size.height=47;
	frame.origin.x=8; frame.origin.y=8;
	AsyncImageView* asyncImage = [[[AsyncImageView alloc]
					initWithFrame:frame] autorelease];

Ossia, creiamo il frame delle dimensioni che ci interessano (nel mio caso 47×47) e decidiamo dove farlo apparire (in questo caso coordinate x=8 e y=8).

Successivamente:

asyncImage.tag = 999;
	NSURL *url = [NSURL URLWithString: sciopero.icona];	
	[asyncImage loadImageFromURL:url];
	[cell.contentView addSubview:asyncImage];

E il gioco é fatto!

Ricordatevi di mettere l’import:

#import "AsyncImageView.h"

Non ho scritto io quella classe, e purtroppo non ricordo dove l’ho pescata, peró ne ho trovate diverse , e questa l’ho personalizzata in diverse parti.

Questo stesso codice l’ho usato giá in parecchie applicazioni:

      iQuimall, mi serviva per caricare le cover/skin degli iphone via web
      iScioperi Trasporti – dovevo caricare tutti i dati comprensive di immagini da un mio XML su web
      (questo spezzone di codice viene proprio da lí!)
      Tutte le altre mie app, che hanno nel tab bar l’opzione “Altre App” appare la lista completa delle
      applicazioni da me realizzate, e cliccando sulla riga si va direttamente sull’AppStore per l’acquisto!

Spero vi sia utile!

Share this story:
  • tweet

Tags: asincronoasynccaricare immagini iphonedownload asincrono iphoneimmaginitableTutorial Pratici

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • T#014 – Un web server per scaricare files e immagini

    2 Dicembre 2009 - 11 Comments

Author Description

Sono un consulente informatico di 34 anni. Lavoro da circa 15 anni presso varie societá in italia, attualmente sono in FAO. Sviluppo in tutti i linguaggi di programmazione, da Java a C++, dal PHP ad Adobe Flex. Ultimamente ho comprato un iPhone e sto sviluppando per questo magnifico dispositivo, Attualmente sull'appStore trovate PuntiPatente+ (al primo posto da venerdí 9 aprile) e ricette Romane.

7 Responses to “T#067 – Caricare immagini nelle tabelle in modalità asincrona”

  1. 30 Luglio 2010

    andreaAppCode

    ma se usiamo dei thread possiamo ottenere gli stessi risultati o sbaglio?

  2. 31 Luglio 2010

    Tweets that mention Caricare immagini nelle tabelle in modalità asincrona [iPhone SDK] | devAPP -- Topsy.com

    […] This post was mentioned on Twitter by David Funaro, devAPP. devAPP said: Caricare immagini nelle tabelle in modalità asincrona http://bit.ly/cBorop […]

  3. 11 Agosto 2010

    Lele

    Ciao eccomi di nuovo qui a leggervi dopo essere tornato dalle ferie, questo articolo mi e’ utile molto, difatti stavo scrivendo una semplice app che scarica gli articolida un feed rss e le img caricate insieme alla cella rallentano di molto lo scrolling della view 🙂 ora provo, grazie in anticipo

  4. 11 Agosto 2010

    Lele

    Ho provato la classe per il caricamneto asincrono delle img, ora ho risolto il mio problema, lo scrolling dei feed rss e’ rapido e fluido con le img che vengono caricate successivamente, grazie mille a presto 🙂

  5. 26 Agosto 2010

    Francesco Burelli

    Ottimo tutorial, davvero interessante, ma vorrei aggiungere delle informazioni: se avessimo una tabella di tanti elementi (troppi) scrollando in fretta tutta la tabella si andrebbero a creare tantissime richieste per scaricare le icone e tantissimi “cancel” inutilmente, infatti se notiamo attentamente l’applicazione “App Store” vediamo che finché non stacchiamo il dito dallo schermo o comunque finché lo scrolling non si ferma “App Store” non carica le icone. Se vi posizionate all’inizio della tabella e scollate senza fermarvi fino in fondo, noterete che le icone caricate saranno solo quelle all’inizio e alla fine della tabella poiché l’app carica le icone solo quando la tabella è ferma.
    Quindi secondo me andrebbe fatto qualcosa di diverso utilizzando magari qualche metodo del delegato della tabella: quando la tabella smette di scorrere allora scarico le icone dal link per esempio.

  6. 14 Ottobre 2010

    Fabio


    Francesco Burelli:

    Ottimo tutorial, davvero interessante, ma vorrei aggiungere delle informazioni: se avessimo una tabella di tanti elementi (troppi) scrollando in fretta tutta la tabella si andrebbero a creare tantissime richieste per scaricare le icone e tantissimi “cancel” inutilmente, infatti se notiamo attentamente l’applicazione “App Store” vediamo che finché non stacchiamo il dito dallo schermo o comunque finché lo scrolling non si ferma “App Store” non carica le icone. Se vi posizionate all’inizio della tabella e scollate senza fermarvi fino in fondo, noterete che le icone caricate saranno solo quelle all’inizio e alla fine della tabella poiché l’app carica le icone solo quando la tabella è ferma.
    Quindi secondo me andrebbe fatto qualcosa di diverso utilizzando magari qualche metodo del delegato della tabella: quando la tabella smette di scorrere allora scarico le icone dal link per esempio.

    mi associo a questa richiesta di tutorial.
    grazie mille!

  7. 18 Marzo 2011

    Davide

    Complimenti. E’ possibile utilizzare la stessa classe per scaricare in modo asincronon una pagina web anziche una immagine?
    Grazie

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO