I'm implementing a project that has a Web Service. In this Web Service you save product data, containing the fields: Name, Value, Description and Product Image.
I did some tests by downloading only the data in the format String, which due to the nature of the data, allows a quick download.
The idea of the project is that these downloaded data will be saved in Core Data, where I am already successfully performing only the data in the String format.
However, downloading images only returns the URL where the image is stored, having to be made an independent request.
For the images, I'll save them in the app's directory, and save the address of the disk file in Core Data, not the URL and the image file in Blob format.
But I tried to include the request of the image inside the looping that saves the files in Core Data, however due to different speeds of the download, I am having problems downloading the images.
In order to solve this problem, I divided the request into two parts, one request for data in a String format and another for the images, I created two classes to treat them independently.
To integrate the classes, I inserted the image request into the looping that requests the String data. However, due to the download time between the two, the looping which is a FOR triggers and ends before the first image is downloaded, which generates a logic error by adding the disk address of the images in the wrong way.
Does anyone have any suggestions for this problem?
I'd like to know how I can share class files so they can be evaluated. For here it would be very large.
Class: GDRequestURL Utility: Download the data format String and return an Array containing the dictionary of the downloaded data.
GDRequestURL.h
#import <Foundation/Foundation.h>
#import "URLGloblal.h"
#import "GDResquestURLImage.h"
@interface GDRequestURL : NSObject<NSURLConnectionDelegate>{
NSMutableData *responseData;
NSMutableDictionary *result;
NSMutableArray*cleanArray;
NSString* isPizza;
NSString* isMassa;
NSString* isRodizio;
NSString* isBebidas;
NSString* isEventos;
// Download de imagem
//GDResquestURLImage* imageRequest;
}
@property (nonatomic, strong) NSString* url;
@property (nonatomic, strong) NSString* requestToken;
@property (nonatomic, strong) NSString* httpHeader;
-(void)getDataFromURL;
-(NSMutableArray*)retornaResultado;
@end
GDRequestURL.m
#import "GDRequestURL.h"
@implementation GDRequestURL
- (id)init {
if (self = [super init]) {
isEventos = urlEventos;
isPizza = urlPizzas;
isMassa = urlMassas;
isBebidas = urlBebidas;
isRodizio = urlBebidas;
_requestToken = urlGlobalToken;
_httpHeader = urlGlobalHttpHeader;
// Passo 1 Download image
GDResquestURLImage*imageRequest = [[GDResquestURLImage alloc] init];
[imageRequest getImageFromURL];
}
return self;
}
-(void)getDataFromURL{
// Aqui é executado todo os métodos desta classe e retorna o resultado da consulta em forma de NSMutableDictionary.
// Here runs all the methods of this class and returns the query result in the form of NSMutableDictionary.
[self requestURLApi:_url requestValue:_requestToken httpHeaderField:_httpHeader];
NSLog(@"getDataFromURL");
}
-(void)requestURLApi:(NSString *)requestURLString requestValue:(NSString*)value httpHeaderField:(NSString*)headFiedl{
NSLog(@"requestURLApi");
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:requestURLString]];
[req setValue:value forHTTPHeaderField:headFiedl];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
[conn start];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"Connection pega data");
responseData = [[NSMutableData alloc] init];
NSError* error;
[responseData appendData:data];
result = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableContainers error:&error];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Connection did finish loading");
// Aqui deve ser implementada a logica para descompactação dos dados de seu JSON.
// Mantenha a lógica apenas acrecentando campos (chaves) conforme o seu JSON gerado na Goldark
// Here the logic should be implemented for unpacking the data from your JSON.
// Keep logic just prepending the name and fields (keys) as your JSON generated in Goldark
// Este modelo é somente para exemplo.
// This model is only for example.
#pragma mark - Se Pizzas
if([isPizza isEqual:_url]){
// Recebe o array Data
NSMutableArray* arrayDataReceived = [result objectForKey:@"data"];
cleanArray = [[NSMutableArray alloc]init];
for ( NSMutableDictionary* valuesDict in arrayDataReceived) {
NSMutableDictionary* cleanDict = [[NSMutableDictionary alloc]init];
[cleanDict setObject: [valuesDict objectForKey:@"nome"] forKey:@"nome"];
[cleanDict setObject: [valuesDict objectForKey:@"valorquarto"]forKey:@"valorquarto"];
[cleanDict setObject: [valuesDict objectForKey:@"valormedio"]forKey:@"valormedio"];
[cleanDict setObject: [valuesDict objectForKey:@"valorgrande"]forKey:@"valorgrande"];
[cleanDict setObject: [valuesDict objectForKey:@"descricao"]forKey:@"descricao"];
// Pega URL da imagem baixa e salva em disco e retorna o path em disco para o Core Data.
// GDResquestURLImage*imageRequest = [[GDResquestURLImage alloc] init];
// imageRequest.urlImage = [valuesDict objectForKey:@"imagem"];
// [imageRequest getImageFromURL];
// [cleanDict setObject: [imageRequest retornaImagem] forKey:@"imagem"];
// Armazena os dicionarios em um Array
[cleanArray addObject:cleanDict];
}
// NSLog(@"%@",cleanArray);
}
}
-(NSMutableArray*)retornaResultado{
NSLog(@"retorna resultado");
NSMutableArray* array =[ [NSMutableArray alloc] initWithArray:cleanArray];
return array;
}
@end
Below is the class responsible for downloading the images, it is identical to String. It has the same functionality, download the images, save to disk and return the file path to the image file on disk.
GDRequestURLImage.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface GDResquestURLImage : NSObject<NSURLConnectionDelegate>{
NSMutableData *responseData;
NSMutableDictionary *result;
UIImage* imagemRecebida;
NSString *caminhoImagemEmDisco;
NSMutableDictionary* dicionarioCaminhoImagemEmDisco;
int numero;
}
@property (nonatomic, strong) NSString* urlImage;
@property (nonatomic, strong) NSString* requestToken;
@property (nonatomic, strong) NSString* httpHeader;
-(void)getImageFromURL;
-(NSString*)retornaImagem;
-(id)initWithURLToRequest:(NSString*)urlImage requestValue:(NSString*)requestToken httpHeaderField:(NSString*)httpHeader;
@end
GDRequestURLImage.m
#import "GDResquestURLImage.h"
@interface GDResquestURLImage ()
@end
@implementation GDResquestURLImage
-(id)initWithURLToRequest:(NSString*)urlImage requestValue:(NSString*)requestToken httpHeaderField:(NSString*)httpHeader {
if (self = [super init]) {
numero = 0;
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlImage]];
[req setValue:requestToken forHTTPHeaderField:httpHeader];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
[conn start];
}
return self;
}
-(void)getImageFromURL{
// Aqui é executado todo os métodos desta classe e retorna o resultado da consulta em forma de NSMutableDictionary.
// Here runs all the methods of this class and returns the query result in the form of NSMutableDictionary.
[self requestURLApi:_urlImage requestValue:_requestToken httpHeaderField:_httpHeader];
NSLog(@"1 -Inicio de download de imagem...\n");
}
-(void)requestURLApi:(NSString *)requestURLString requestValue:(NSString*)value httpHeaderField:(NSString*)headFiedl{
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:requestURLString]];
[req setValue:value forHTTPHeaderField:headFiedl];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
[conn start];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"2 - Connection DidReceiveData.\n");
// As imagens ja vem em formato binario, portanto basta passar para responder (Tipo: NSMutableData).
responseData = [[NSMutableData alloc] init];
[responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"3 - ConnectionFinishLoading.\n");
NSLog(@"Fim de conexao");
for (UIImage* imagemTemp in responseData) {
imagemRecebida = [[UIImage alloc]init];
imagemRecebida = imagemTemp;
// paga endereço da pasta
NSString* enderecoPastaDisco = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* nomeImagem = [NSString stringWithFormat:@"%dTeste",numero];
caminhoImagemEmDisco = [NSString stringWithFormat:@"%@/%@.jpg",enderecoPastaDisco,nomeImagem];
NSData *data2 = [NSData dataWithData:UIImageJPEGRepresentation(imagemRecebida, 1.0f)];//1.0f = 100% quality
[data2 writeToFile:caminhoImagemEmDisco atomically:YES];
// retorna imagem
NSLog(@"CaminhoImagem: %@",caminhoImagemEmDisco);
numero ++;
}
}
-(NSString*)retornaImagem{
return caminhoImagemEmDisco;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(@"Erro de request: %@",error);
}
@end
As I'm doing constant tests to try to solve, there are variables that will not make sense apparently. But the code as a whole can be understood.