Я оптимизирую процесс загрузки и показа приложения для iOS. В этом приложении у меня есть объект Noticia, который содержит, среди прочего, URL-адрес изображения (хранится как строка) и объект UIImage с фактическим изображением.Показать изображения как только они будут загружены?
Сейчас все делается синхронным, и это открывает соединение для каждого изображения, которое он загружает так:
NSURL *imageURL = [NSURL URLWithString:noti.urlImagen];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
Итак, когда есть много новостей для загрузки, это занимает много времени для загрузки, и приложение абсолютно не отвечает, пока это происходит.
Поэтому я меняю его прямо сейчас, теперь я могу асинхронно загружать все изображения с кодом, найденным в this question, но теперь мне нужно показать их, как только они загрузятся в список новостей. Как я могу это сделать?
noticia объект Noticia.h
#import <UIKit/UIKit.h>
@interface Noticia : NSObject
@property (nonatomic) int identificacion;
@property (nonatomic, strong) NSString *titulo;
@property (nonatomic, strong) NSString *descripcion;
@property (nonatomic, strong) NSString *fecha;
@property (nonatomic, strong) NSString *urlImagen;
@property (nonatomic, strong) NSString *urlNoticia;
@property (nonatomic, strong) NSString *categoria;
@property (nonatomic, strong) NSString *fuente;
@property (nonatomic, strong) NSString *contenido;
@property (nonatomic) int tipo;
@property (nonatomic) UIImage *imagen;
-(id)initWithTitulo:(NSString *)ti descripcion:(NSString *)de fecha:(NSString *)fe urlImagen:(NSString *)uri urlNoticia:(NSString *)urn categoria:(NSString *)ca fuente:(NSString *)fu contenido:(NSString *)co tipo:(int)tip;
@end
Noticia.m
#import "Noticia.h"
@implementation Noticia
@synthesize titulo, descripcion, urlImagen, urlNoticia, categoria, fuente, contenido, tipo, fecha;
-(id)initWithTitulo:(NSString *)ti descripcion:(NSString *)de fecha:(NSString *)fe urlImagen:(NSString *)uri urlNoticia:(NSString *)urn categoria:(NSString *)ca fuente:(NSString *)fu contenido:(NSString *)co tipo:(int)tip{
if(self = [super init]){
self.titulo = ti;
self.descripcion = de;
self.fecha = fe;
self.urlImagen = uri;
self.urlNoticia = urn;
self.categoria = ca;
self.fuente = fu;
self.contenido = co;
self.tipo = tip;
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"Noticia:\nTitulo:%@\nDescripcion:%@\nFecha:%@\nurlImagen:%@\nurlNoticia:%@\nCategoria:%@\nFuente:%@\nContenido:%@\nTipo:%i",titulo, descripcion, fecha, urlImagen, urlNoticia, categoria, fuente, contenido, tipo];
}
@end
Как Noticia получает загружены (Асинхронный способ)
-(NSMutableArray *)traerNoticias{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kEndPointNews]];
if (data != NULL) {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *arregloNoticias = [[NSMutableArray alloc]init];
for (NSDictionary *noticia in json) {
NSDictionary *noticiaInfo = [noticia objectForKey:@"noticia"];
Noticia *noti = [[Noticia alloc]initWithTitulo:[noticiaInfo objectForKey:@"titulo"] descripcion:[noticiaInfo objectForKey:@"descripcion"] fecha:[noticiaInfo objectForKey:@"fecha"] urlImagen:[noticiaInfo objectForKey:@"urlImagen"] urlNoticia:[noticiaInfo objectForKey:@"urlNoticia"] categoria:@"a" fuente:@"a" contenido:[noticiaInfo objectForKey:@"contenido"] tipo:[[noticiaInfo objectForKey:@"destacada"]intValue]];
noti.identificacion = [[noticiaInfo objectForKey:@"id"]intValue];
NSLog(@"%@", noti);
//NSURL *imageURL = [NSURL URLWithString:noti.urlImagen];
//NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
NSData *imageData = nil;
noti.imagen = [UIImage imageWithData:imageData];
[arregloNoticias addObject:noti];
}
arregloNoticias = [self cargarImagenesAsincrono:arregloNoticias];
return arregloNoticias;
}else{
return nil;
}
}
-(NSMutableArray *)cargarImagenesAsincrono:(NSMutableArray *)arregloNoticias
{
NSMutableArray *urlsNoticias = [[NSMutableArray alloc]init];
for (Noticia *Noticias in arregloNoticias) {
NSURL *url = [NSURL URLWithString:Noticias.urlImagen];
[urlsNoticias addObject:url];
}
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 7;
NSMutableArray *imagenes = [[NSMutableArray alloc]init];
for (NSURL* url in urlsNoticias)
{
[queue addOperationWithBlock:^{
NSData *data = [NSData dataWithContentsOfURL:url];
[imagenes addObject:data];
}];
}
int i=0;
for (NSData *imageData in imagenes) {
Noticia *noti=[arregloNoticias objectAtIndex:i];
noti.imagen=[UIImage imageWithData:imageData];
[arregloNoticias replaceObjectAtIndex:i withObject:noti];
i++;
}
return arregloNoticias;
}
Основной интерфейс рассчитывает уже есть объект UImage, готовый в объекте Noticia для его отображения. Я также видел, что последнее утверждение для cargarImagenesAsincrono никогда не происходит, поэтому исходный массив с объектами Noticia никогда не обновляется с изображениями.
Как я могу это достичь? Основной интерфейс находится в другом файле.
Я могу разместить больше кода, если вам это нужно. (извините за испанский)
Привет compañero. Чтобы загрузить и показать изображения асинхронно, я использую AFNetworking. Конкретно AFNetworking/UIImageView + AFNetworking.h: https://github.com/AFNetworking/AFNetworking/blob/master/UIKit%2BAFNetworking/UIImageView%2BAFNetworking.h – nigelman