I am using collection View to display the product data in each cell. Each time when user refreshes collectionview, it fetches data from the server again.
I need to know is there a caching mechanism available which caches downloaded images. I want to download only recently updated products which are not cached.
NSURL *url = [NSURL URLWithString:#"http://www.myURL/productAll.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *myError = nil;
id res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];
items = [[NSMutableArray alloc] init];
for (int i=0; i<[res count]; i++) {
NSString *arrayResult = [[res objectAtIndex:i]objectForKey:#"image"];
NSData *data = [[NSData alloc] initWithBase64EncodedString:arrayResult options:NSDataBase64DecodingIgnoreUnknownCharacters];
UIImage *captcha_image = [[UIImage alloc] initWithData:data];
[items addObject:captcha_image];
}
[collectionView reloadData];
}];
Use NSURLCache to setup memory and disk cache like this:
int cacheSizeMemory = xxxxx; //in memory cache
int cacheSizeDisk = xxxxx; //disk cache
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:#"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
Related
I'm new to Objective-C, just wondering how to use NSArray object outside from JSON.
For example:
NSURL *url = [NSURL URLWithString:#"http://acumen-locdef.elasticbeanstalk.com/service/countries"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSMutableArray *myFinalListArray = [[NSMutableArray alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSMutableArray *greeting = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
for (NSDictionary *countryList in greeting) {
[myFinalListArray addObject:countryList[#"name"]];
}
}
NSLog(#"%#",myFinalListArray); //(This one showing all results..)
}];
NSLog(#"%#",myFinalListArray); //(This one giving empty result)
I have defined myFinalListArray and added objects in for loop.
If you use NSLog inside the loop or outside the loop it will show you results. But if I use this after }]; (after the code is ending.),
it's giving me empty array.
If you are accessing myFinalListArray in tableview then you can reload tableview inside the block after fetching data.
Or if you are accessing this array in some other task then you have to make notification call (have to add observer) and then post notification that will call some other method and access your array there and do your further stuff.
The block of code associated with sendAsynchronousRequest isn't executed until the network fetch has completed; this takes some time. While the network fetch is happening your code continues to execute, starting with the line immediately after sendAsynchronousRequest which is NSLog(#"%#",myFinalListArray); - but because the network operation hasn't completed you get an empty array.
In the block you need to include the code that you need to process the array, update your user interface or whatever (If you update UI make sure you dispatch the operation on the main thread)
This will work. You can try with this.
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *myFinalListArray = [[NSMutableArray alloc] init];
//Pass here the reference the a array. It will return you the array of you county when downloaded complete.
[self getURLResponse:&myFinalListArray];
NSLog(#"countryArray:%#",myFinalListArray);
}
-(void)getURLResponse:(NSMutableArray**)countryArray{
NSURL *url = [NSURL URLWithString:#"http://acumen-locdef.elasticbeanstalk.com/service/countries"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSMutableArray *myFinalListArray = [[NSMutableArray alloc] init];
NSURLResponse *response;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:
request returningResponse:&response error:&error];
NSMutableArray *greeting = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
for (NSDictionary *countryList in greeting) {
[myFinalListArray addObject:countryList[#"name"]];
}
*countryArray = [[NSMutableArray alloc]initWithArray:myFinalListArray copyItems:YES];
}
-(void)sendRequest
{
NSURL *url = [NSURL URLWithString:#"http://acumen-locdef.elasticbeanstalk.com/service/countries"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSMutableArray *myFinalListArray = [[NSMutableArray alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError) {
if (data.length > 0 && connectionError == nil)
{
NSMutableArray *greeting = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
if( !myFinalListArray )
{
myFinalListArray=[[NSMutableArray alloc]init];
}
for (NSDictionary *countryList in greeting) {
[myFinalListArray addObject:countryList[#"name"]];
}
}
[self printArray];
}];
}
//create method that will execute after response
-(void) printArray
{
NSLog(#"%#",myFinalListArray); //(This one showing all results..)
}
Use
__block NSMutableArray *myFinalListArray = [[NSMutableArray alloc] init];
This should work.
Happy Coding.
sendAsynchronousRequest runs asynchronously, meaning that the code below is already performed while the request is still running, so the NSLog is logging the empty array.
Only when the request finishes, the array is filled up but your outer NSLog was already performed.
**In this code When add breakpoint from viewdidload( ) function then i got greetingArray.count zero but when i add breakpoint at the for loop then it works properly and i got the results 3 as the values of the greetingArray. What is the possible reason that no getting the data from server.There is no problem with server side.I already check for it.
- (void)viewDidLoad
{
[super viewDidLoad];
greetingArray = [[NSMutableArray alloc] init];
greetingDictionary = [[NSMutableDictionary alloc] init];
NSString *connectionString;
connectionString=[NSString stringWithFormat:#"http://xxx.xxx.x.xx/TestMgt/api/%#",self.fieldName];
NSURL *url = [NSURL URLWithString:connectionString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSLog(#"----------------------------------------------------");
NSLog(#"Data length is = %d",data.length);
greetingMArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
NSLog(#"%#",greetingMArray);
for(int i = 0 ; i< greetingMArray.count; i++)
{
greetingDictionary = (NSMutableDictionary *)[greetingMArray objectAtIndex:i];
NSLog(#"%#",greetingDictionary);
ConnectionOvertime *overtime = [[ConnectionOvertime alloc] init];
overtime.entryDate=[greetingDictionary valueForKey:#"EntryDate"];
[greetingArray addObject:overtime];
NSLog(#"%d",greetingArray.count);
}
}
}];
}
if you don't get any answer try jsonFramework library and import sbjsonParser.h
for Example try below code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.ChapterID=[[NSMutableArray alloc]init];
self.ChapterName=[[NSMutableArray alloc]init];
NSURL *url=[NSURL URLWithString:#"https://www.coursekart.com/webservice/load-subjects.php?api_key=68410920GHJFLAC878&standard_id=2&format=json"];
NSURLRequest *request=[[NSURLRequest alloc]initWithURL:url];
NSError *error;
NSURLResponse *response;
NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(data!=nil)
{
NSString *content=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(content.length!=0)
{
SBJsonParser *parser=[[SBJsonParser alloc]init];
NSArray *dir=[[parser objectWithString:content]objectForKey:#"SubjectList"];
for(int i=0;i<dir.count;i++)
{
NSDictionary *array=[dir objectAtIndex:i];
NSArray *data=[array objectForKey:#"Data"];
NSDictionary *dat=(NSDictionary *)data;
NSString *idCh=[dat objectForKey:#"id"];
NSString *slug=[dat objectForKey:#"slug"];
[ChapterID addObject:idCh];
[ChapterName addObject:slug];
// NSLog(#"%#",[ChapterID objectAtIndex:0]);
//NSLog(#"%#",[ChapterName objectAtIndex:0]);
}
}
}
}
how can i display image into UICollectionView using Cache and display large image into another
View on UICollectionView didSelect. Here both large and thumb image on CollectionView so next view large image not blank.using EMAsyncImageView
NSURL *url = [NSURL URLWithString:#"http://leewayinfotech.com/mobile/girlwallpaper/api.php?category=abstract&device=i5&hits=all"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//NSLog(#"Response String=%#",responseString);
NSError *jsonError;
NSData *trimmedData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:trimmedData options:NSJSONReadingAllowFragments error:&jsonError];
if (jsonError) {
NSLog(#"JSON parse error: %#", jsonError);
return;
}
obj_Array=[[NSMutableArray alloc] init];
obj_Array=[json objectForKey:#"wallpaper"];
//NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.thumb_img_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.device_img_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.imgNo_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
for (int i=0; i<[obj_Array count]; i++) {
ImgClass *obj_Class=[[ImgClass alloc] init];
obj_Class.main_id=[[[obj_Array objectAtIndex:i] valueForKey:#"id"] integerValue];
[obj_Class.thumb_img_Array addObject:[[[obj_Array objectAtIndex:i] objectForKey:#"images"] objectForKey:#"image_thumb"]];
[obj_Class.device_img_Array addObject:[[[obj_Array objectAtIndex:i] objectForKey:#"images"] objectForKey:#"image2"]];
NSLog(#"Thumb-->%#\n\nDevice-->%#",[obj_Class.thumb_img_Array description],[obj_Class.device_img_Array description]);
[appDelg.my_Array addObject:obj_Class];
}
you use the EGOImageView for image caching support.
You can use SDWebImage.Using SDWebImage you can set image using imageURLString like below with CacheType.
[yourImgView setImageWithURL:[NSURL URLWithString:imageURLString]
placeholderImage:[UIImage imageNamed:#"noimage.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
if (!error && image)
{
}
}];
Hope it will helps you..
in my app lets say there is 2 views ViewA and ViewB
in ViewA there are buttons for user to select option. And if he push one of them i will pull some images from web via web service and download them to the user's machine also i will put their paths to an array.
Then in ViewB i want to get images from that array and show them in image views
this is how i download images
-(void)startDownload
{
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:#"http://xxxx.com/Tulips.jpg"];
[arr addObject:#"http://xxxx.com/Koala.jpg"];
[arr addObject:#"http://xxxx.com/Penguins.jpg"];
for (int i=0; i<[arr count]; i++) //download array have url links
{
NSURL *URL = [NSURL URLWithString:[arr objectAtIndex:i]];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc]initWithURL:URL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if([data length] > 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
//make your image here from data.
UIImage *imag = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [array objectAtIndex:0];
NSString *imgstr=[NSString stringWithFormat:#"%d",i];
NSString *pngfilepath = [NSString stringWithFormat:#"%#sample%#.jpg",docDir,imgstr];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(imag)];
[data1 writeToFile:pngfilepath atomically:YES];
img = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:pngfilepath]];
NSLog(#"file is written");
}
else if ([data length] == 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
NSLog(#"No Data!");
}
else if (![[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"]){
NSLog(#"Error = %#", error);
}
}];
}
}
when i run the app i see that file is written log is working so i think downloading the images is successful but i can't show image in imageview
you may think quiz up app on the store for understanding my problem clearly. quiz up first downloading questions' images then use them in another view. that's what i want exactly.
if my download code is correct how can i show them?
This code will allow you to download an image from the web, and does not require that the image be saved in the document directory:
NSMutableArray *arry = [[NSMutableArray alloc] init];
[arry addObject:#"https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRr0WK-Q2t4Xxr1b6Kl7-lXdVEIh_Hj3HiDXk--Qg_0UAY0Y96P6w"];
[arry addObject:#"https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRr0WK-Q2t4Xxr1b6Kl7-lXdVEIh_Hj3HiDXk--Qg_0UAY0Y96P6w"];
[arry addObject:#"https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRr0WK-Q2t4Xxr1b6Kl7-lXdVEIh_Hj3HiDXk--Qg_0UAY0Y96P6w"];
for (int i=0; i<[arry count]; i++) //download array have url links
{
NSString *string=[arry objectAtIndex:i];
NSURL *url=[NSURL URLWithString:string];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
UIImage *imagemain=[UIImage imageWithData:data];
// CGSize size=imagemain.size;
// UIImage *compimage=[appdel resizeImage:imagemain resizeSize:CGSizeMake(45,45)];
//
// Cell.imgProfile.image=compimage;
// // CGSize size1=compimage.size;
imageView.image=imagemain;
}];
}
Are you updating your UIImageView on the main thread, you can't update UI elements from a background thread. Try
dispatch_sync(dispatch_get_main_queue(),
^{
imageView.image = yourImage;
});
You have to use SDWebImage to cache the image. means the url will not be hit again and again.
#import "UIImageView+WebCache.h"
-(void)startDownload
{
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:#"http://xxxx.com/Tulips.jpg"];
[arr addObject:#"http://xxxx.com/Koala.jpg"];
[arr addObject:#"http://xxxx.com/Penguins.jpg"];
for (int i=0; i<[arry count]; i++) //download array have url links
{
NSString *string=[arry objectAtIndex:i];
NSURL *url=[NSURL URLWithString:string];
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:url progress:^(NSUInteger receivedSize, long long expectedSize)
{
// progression tracking code
}completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
{
if (image)
{
// here you can setup imageView frames and set the image on imageView
imageView.image=image;
}
}];
}
}
}
There are, for example, 100 JSON files and appropriate 100 images on my ftp server.
1.With loading JSON where are no bug (I hope)
NSString *recipesPath = #"ftp://.../recipes/";
NSString *recipeFileName = [NSString stringWithFormat:#"00001.json", recipeCode];
NSString *recipeFileFullPath = [recipesPath stringByAppendingString:recipeFileName];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeFileFullPath]];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError *error = nil;
NSDictionary *recipeDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
2.But images can not be loaded
NSString *recipeImageName = #"recipeImages/00001-1.jpg";
NSString *recipeImageFullPath = [recipesPath stringByAppendingString:recipeImageName];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:recipeImageFullPath]];
if (request) {
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (responseData) {
UIImage *image = [UIImage imageWithData:responseData];
}
}
responseData nearly always is nil.
May be there is the other method?
All this code is in MyMethod which I execute in NSOperationQueue:
operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(MyMethod) object:nil];
[operationQueue addOperation:operation];
EDIT: image sizes are not big - from 50 to 100 kbyte
EDIT: can image file extension affect to downloading process?
You can try this:
NSURL *url = [NSURL URLWithString:recipeImageFullPath];
NSData *data = [NSData alloc] initWithContentsOfURL:url];
Please try to test it:
NSError *requestError;
NSURLResponse *urlResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
/* Return Value
The downloaded data for the URL request. Returns nil if a connection could not be created or if the download fails.
*/
if (responseData == nil) {
// Check for problems
if (requestError != nil) {
...
}
}
else {
// Data was received.. continue processing
}