I have successfully retrieved the image (lets say user profile pic) from parse, and i'm displaying it in the ios app. But if there is no image in the file column, then i want to display default image which is stored in the locally (not in parse), not successful.
My simple question is, how to check if there is image or not ? Below is the simple code;
PFFile *userImage = [object objectForKey:#"profilePic"]; __block UIImage *userProfilePic =[[UIImage alloc]init];
[userImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
//this block will execute only if there is image
if(data) {
userProfilePic = [UIImage imageWithData:data];
userPic.image=userProfilePic;
}
//this block is not at all executing. This block should execute when user doesn't have their profile uploaded
if(!data) {
UIImage *userProfileDefaultPic = [[UIImage alloc]init];
userProfileDefaultPic=[UIImage imageNamed:#"defaultprofile.png"];
userPic.image=userProfileDefaultPic;
}
}
}];
Hope you can help me. Thanks in advance.
Pradeep
At last found the solution !
(!data) will not execute , instead we need to check if the PFFile and the UIImage to store PFFile has image or not, like below;
PFFile *userImage = [object objectForKey:#"profilePic"];
__block UIImage *userProfilePic =[[UIImage alloc]init];
if(userImage && ![userProfilePic isEqual:[NSNull null]]) //This is important to check if the file if image is there or not and if not, then display default pic in else part
{
[userImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if(!error)
{
userProfilePic = [UIImage imageWithData:data];
userPic.image=userProfilePic;
}
}];
}
else
{
userProfilePic =[UIImage imageNamed:#"defaultprofilepic.png"];
userPic.image=userProfilePic;
}
Your code already does that. You just need to set your image on the main thread and not background thread.
if(!data) { [dispatch_async(dispatch_get_main_queue(), ^{
UIImage *userProfileDefaultPic = [[UIImage alloc]init];
userProfileDefaultPic=[UIImage imageNamed:#"defaultprofile.png"];
userPic.image=userProfileDefaultPic;
}}];
Related
From my web service i am getting multiple sized images. I m loading them in TableView. When i m loading them new images which haven't cached yet flickers between placeholder and original image, or sometimes the image appear as smaller than the usual size. But just a bit scrolling down or up actually fix the problem but i want them to be at original size from the beginning. But it would appear in original shape from the next time i suppose because the picture was already cached
Initially
After a bit scrolling
My code in cellForRowAtIndexPath:
[cell.image sd_setImageWithURL:[NSURL URLWithString:[NSMutableString stringWithFormat:#"%#app/media/access/pictures?p=%#",baseurl,data.picPath]]
placeholderImage:[UIImage imageNamed: #"image_loader.gif"]];
then in heightForRowAtIndexPath:
NSURL *filePath = [NSURL URLWithString:[NSMutableString stringWithFormat:#"%#app/media/access/pictures?p=%#",baseurl,data.picPath]];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:filePath];
UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
self.img = image;
if (self.img.size.width > CGRectGetWidth(self.view.bounds)) {
CGFloat ratio = self.img.size.height / self.img.size.width;
return CGRectGetWidth(self.view.bounds) * ratio+140;
} else {
return self.img.size.height+180;
}
I have visited https://github.com/rs/SDWebImage and in their common problem section they have mentioned about the problem but the suggested solution didn't work for me!!!
Actually what i did, i checked if the image was cached already and if not i have downloaded it asynchronously under heightForRowAtIndexPath:
if(image != NULL)
{
self.img = image;
}
else
{
SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader];
[downloader downloadImageWithURL:filePath
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
// progression tracking code
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
if (image && finished) {
// do something with image
self.img = image;
}
}];
}
The problem is that I am calling multiple webservices on my homepage and the webservice is returning me the images and text from the server. During this process the UI become fully unresponsive for say 1-2 minutes which is looking very bad as I cant do anything. I heard about dispatch and tried to implement it but I dont get any results.May be I am doing something wrong.
What I want now that I want to that I want to run this process in background So that a user can interact with the UI during the fetching operation from the server. I am implementing my code just tell me where to use dispatch.
-(void)WebserviceHomeSlider{
if([AppDelegate appDelegate].isCheckConnection){
//Internet connection not available. Please try again.
UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:#"Internate error" message:#"Internet connection not available. Please try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
return;
}else {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[manager GET:ServiceUrl#"fpMainBanner" parameters:nil success:^(AFHTTPRequestOperation *operation,id responseObject)
{
//NSLog(#"JSON: %#", responseObject);
arrSlider = [responseObject objectWithJSONSafeObjects];
[_slideshow setTransitionType:KASlideShowTransitionSlide];
_slideshow.gestureRecognizers = nil;
[_slideshow addGesture:KASlideShowGestureSwipe];
// [_slideshow addImagesFromResources:[self getImages]]; // Add
// [_slideshow addTextFromResources:[self getText]];
// [slideShow subtextWithImages:[self getsubText]];
[_slideshow addImagesFromResources:[self getImages] stringArray:[self getText] stringsubArray:[self getsubText]];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
}
Just tell me where to use dispatch or edit my code using dispatch if possible. I have gone through some examples but still my concept is not clear. Which dispatch method id best (DEFAULT or BACKGROUND). I will be very thankful to You.
This is the code you are looking for . Just tell me where to edit it using dispatch
-(NSArray *)getText{
NSMutableArray *textArr = [[NSMutableArray alloc] init];
for(int i=0; i<[arrSlider count];i++)
{
texxt=[[arrSlider objectAtIndex:i ]valueForKey:#"title" ];
[textArr addObject:[texxt uppercaseString]];
}
return textArr;
}
-(NSArray *)getsubText{
NSMutableArray *subtext = [[NSMutableArray alloc] init];
for(int i=0; i<[arrSlider count];i++)
{
subbtext=[[arrSlider objectAtIndex:i ]valueForKey:#"tagline_value" ];
if(i==8)
{
subbtext=#"MAKE YOURSELF STAND OUT GET YOUR FREE CARDS!";
}
NSLog(#"subtext is,,.,.,,.,%#.%#",#"k",subbtext);
[subtext addObject:[subbtext uppercaseString]];
}
return subtext;
}
-(NSArray *)getImages
{
NSMutableArray *mArr = [[NSMutableArray alloc] init];
for(int i=0; i<[arrSlider count];i++)
{
pathh=[[arrSlider objectAtIndex:i ]valueForKey:#"filepath" ];
NSString *newString = [pathh stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL *imageURL = [NSURL URLWithString:newString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *originalImage = [UIImage imageWithData:imageData];
CGSize destinationSize = CGSizeMake(320, 158);
UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// [whotshotimgview setImage:image];
[mArr addObject: img];
}
return mArr;
}
[_slideshow addImagesFromResources:[self getImages] stringArray:[self getText] stringsubArray:[self getsubText]];
The problem here is that you didn't showed implementation of addImagesFromResources method. You probably have to implement GCD in this method because i guess you are fetching images and setting on UI by this your main thread is getting blocked.
You are trying to access the UIView from thread other than the main which causes the UI unresponsiveness.
Please use this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[_slideshow setTransitionType:KASlideShowTransitionSlide];
_slideshow.gestureRecognizers = nil;
[_slideshow addGesture:KASlideShowGestureSwipe];
// [_slideshow addImagesFromResources:[self getImages]]; // Add
// [_slideshow addTextFromResources:[self getText]];
// [slideShow subtextWithImages:[self getsubText]];
[_slideshow addImagesFromResources:[self getImages] stringArray:[self getText] stringsubArray:[self getsubText]];
});
What I think is that your UI hangs due to downloading of image.
So you should use SDWebImage library that can help you to cache image and also prevent the UI getting hang. Using SDWebImage you can show the loader for the time the image is not loaded and it will cache the image. So from next time no image will be downloaded and also the UI will not hang. The link for complete reference to SDWebImage is :https://github.com/rs/SDWebImage
This block blocking your main UI to perform tasks so update this block as follow,
for(int i=0; i<[arrSlider count];i++)
{
pathh=[[arrSlider objectAtIndex:i ]valueForKey:#"filepath" ];
NSString *newString = [pathh stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
NSURL *imageURL = [NSURL URLWithString:newString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *originalImage = [UIImage imageWithData:imageData];
CGSize destinationSize = CGSizeMake(320, 158);
UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// [whotshotimgview setImage:image];
[mArr addObject: img];
dispatch_async(dispatch_get_main_queue(), ^{
// If you want to refresh your UI simultaniously, you can write statement for that i.e
// yourImageView.image = img;
// Otherwise remove this queue
});
});
}
The main thread should never be used for long processing. Its there for the UI.
AFNetworking provides asynchronous functionality for downloading files. You should also be careful of thrashing the network layer with too many simulatanous downloads. I think 4 or 5 is the max the last time I tested.
So the flow of execution should be as follows.
The controller sets up the slideshow, sends the downloading of the images to a background thread(automatically handled by AFNetworking), passing a completion block to it. In this completion block you need to dispatch the work back to the main thread using GCD, dispatch_async to dispatch_get_get_main_queue
Keep your main thread's run loop available for user interaction.
It is because the images are loading in another thread and you are populating your slider right after getting the data.
It is better to implement this protocol method of KASlidershow to use the slideshow in a more memory efficient way.
(UIImage *)slideShow:(KASlideShow *)slideShow imageForPosition:(KASlideShowPosition)position
{
pathh=[[arrSlider objectAtIndex:i ]valueForKey:#"filepath" ];
NSString *newString = [pathh stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
NSURL *imageURL = [NSURL URLWithString:newString];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *originalImage = [UIImage imageWithData:imageData];
CGSize destinationSize = CGSizeMake(320, 158);
UIGraphicsBeginImageContext(destinationSize);
[originalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// [whotshotimgview setImage:image];
[mArr addObject: img];
return img;
});
}
i didn't try the code but i hope it will work with little changes in variable names. Good luck
NSString *img=[arrImages objectAtIndex:i];
imgScrollView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
I have displayed my code. The URL links have been stored into an array and the images are also fetching into uiimage view, but only the first two images are loaded into the imageview while the others didn't load .
arrImages:
inside image viewhttp://localhost:8888/welcome/company/0/images/TV Repair.png
this is the link present in the arrImages i don't know why first two images has been loading.
FOR LOOP:
for(NSDictionary *DicHoleCategories in ArrCategory)
{
StrName=[DicHoleCategories objectForKey:#"image"];
if(StrName!=nil)
{
subimages=[NSString stringWithFormat:LocalImage"%#",StrName];
[DicAllValues setObject:subimages forKey:#"image"];
NSError *error =nil;
}
[arrImages addObject:[DicAllValues objectForKey:#"image"]];
}
Can anyone find the issue and help me please?
Go through the below coding
//url string
NSString *ImageURL = #"yoururl";
//string to data conversion
NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
//set image
imageView.image = [UIImage imageWithData:imageData];
please follow the below code
if(StrName!=nil)
{
subimages=[NSString stringWithFormat:LocalImage"%#",StrName];
[DicAllValues setObject:subimages forKey:#"image"];
NSError *error =nil;
[arrImages addObject:[DicAllValues objectForKey:#"image"]];//add here!
}
Plz check now and tell me if its working or not!
I want to get thumbnail image or blank image first while app is loading image data from parse database. After finish loading, the image view will display the image I load from parse.
So far, I have following codes
PFFile *thumbnail = object1[#"PostFiles"];
NSData *imageData = [thumbnail getData];
UIImage *image = [UIImage imageWithData: imageData];
I use PFtableviewcontroller. when I scroll down, my code will load image, the controller can't move smoothly.
The issue is that you are running a synchronous call for a task that could take a varying amount of time. Try getting the NSData using InBackgroundWithBlock:
image = nil; //prevent images from being shown erroneously
[thumbnail getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (data && !error) {
image = [UIImage imageWithData:data];
} else {
//maybe set a default image here if there is none?
}
}];
i have try to create an Image Controller for store image and reuse it when need during one instance of application, this is my class
[Nota: the method controllaDictionary search the key of the image if is was just used (explain on detail above)]
-(void)imageContentUrl:(NSString*)imageURL andImage:(UIImage**)image{
NSLog(#"Stampa Immagine Contente URL: %#",imageURL);
NSString* imageName = [[imageURL componentsSeparatedByString:#"/"] lastObject];
if([self controllaDictionary:imageName]){
NSLog(#"||| IMMAGES ---------> Image Exixt in Dictionary");
UIImage* imageInDict = [self controllaDictionary:imageName];
image = &imageInDict;
return;
}else{
UIImage* imageFile = nil;
if([imageName isEqualToString:#""] || imageName == nil){
NSLog(#"||| IMMAGES ------- Null Link");
image = nil;
}
if([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:#"%#/%#",_imageDirectory,imageName]]){
NSLog(#"||| IMMAGES ------- Exist in Folder: %#",[NSString stringWithFormat:#"%#/%#",_imageDirectory,imageName]);
imageFile = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#",_imageDirectory,imageName]];
image = &imageFile;
[self.imageDict setValue:imageFile forKey:imageName];
return;
}else{
NSLog(#"||| IMMAGINI ------- Miss, Start Download at URL: %#",imageURL);
[self downloadImageAtUrl:imageURL andImagePointer:image withHendlerBlock:^(NSError *error, UIImage *image, NSString *urlImage,UIImage** doubleImagePointer) {
if (!error) {
NSLog(#"Stampa Double Pointer IMG -> %#",image);
doubleImagePointer = ℑ
[self saveImage:image andName:imageName];
[self.imageDict setValue:image forKey:imageName];
}else{
NSLog(#"Stampa Errore: %#",error);
}
}];
}
}
}
-(void)downloadImageAtUrl:(NSString*)urlImage andImagePointer:(UIImage**)image withHendlerBlock:(void(^)(NSError* error,UIImage* imageDownloaded,NSString* urlImage,UIImage** doubleImagePointer))dowloadImageBlock{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
UIImage* downloadImg = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlImage]]];
NSError* error = nil;
if (downloadImg) {
NSLog(#"Immagine Acquisita");
}else{
NSLog(#"Errore Download Compilazione Errore");
error = [NSError errorWithDomain:DownloadErrorDomain code:0 userInfo:#{DownloadErrorDomain: #"Errore nel download dell'immagine, non si hanno a disposizione ulteriori strumenti per comprenderne la natura. Effettuare un ceck della URL"}];
}
dowloadImageBlock(error,downloadImg,urlImage,image);
});
}
#end
ok after this i explain you how wath i have to do:
QUickly is a singleton instance that search in a specific Folder if there is a Image.
Yes set image and done, No start dowload then set and done.
I have see that this method is powerfull for memory management because i create a NSMutabeDictionary with the name of image like a key and the UIImage for value so i use only one pointer for multiple instance of same image [then i allocate in memory the image only first time].
-(void)imageContentUrl:imageURL andImage:(UIImage**)image
this method search in the dir if file exist and set the image-> now i would operate like sometime run NSError so i pass to this method an UIImage**
like this
UIImage* image = nil;
[[GestoreImmagini instance] imageContentUrl:#"URL/Immage/For/Download.jpg" andImage:&image];
[self.imageEvent setImage:image];
the in async i set the image.
this is my Idea but the image are downloaded and set (and if i log, are printed on console) but self.imageEvent don't show the image... Some one can help me?
#Edit After Cy-4AH Answer
Correct!! Is my fault... after C++ i have pass more time to work without pointer and i have forgot somting...
tnx but now the second portion of the code after dowload and the return from the block the image was not set... [with correction of *]
[self downloadImageAtUrl:imageURL andImagePointer:image withHendlerBlock:^(NSError *error, UIImage *image, NSString *urlImage,UIImage** doubleImagePointer) {
if (!error) {
NSLog(#"Stampa Double Pointer IMG -> %#",image);
*doubleImagePointer = image;
[self saveImage:image andName:imageName];
[self.imageDict setValue:image forKey:imageName];
}else{
NSLog(#"Stampa Errore: %#",error);
}
}];
why? on theory the pointer is the same...
#Edit After DEBUG
i have found problem here at the log 2.0 , 2.1 and 2.2 the image print (null) and this i correct because i not have set it but in 2.3 i have a crash for BAD_ACCESS like miss all References. and same happens when i print it in the dowloadImageBlock().
-(void)downloadImageAtUrl:(NSString*)urlImage andImagePointer:(UIImage**)image withHendlerBlock:(void(^)(NSError* error,UIImage* imageDownloaded,NSString* urlImage,UIImage** doubleImagePointer))dowloadImageBlock{
NSLog(#" 2.0 - ||| ----- -------- -----------> %#",*image);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(#" 2.1 - ||| ----- -------- -----------> %#",*image);
dispatch_async(queue, ^{
NSLog(#" 2.2 - ||| ----- -------- -----------> %#",*image);
UIImage* downloadImg = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlImage]]];
NSError* error = nil;
if (downloadImg) {
NSLog(#"Immagine Acquisita");
}else{
NSLog(#"Errore Download Compilazione Errore");
error = [NSError errorWithDomain:DownloadErrorDomain code:0 userInfo:#{DownloadErrorDomain: #"Errore nel download dell'immagine, non si hanno a disposizione ulteriori strumenti per comprenderne la natura. Effettuare un ceck della URL"}];
}
NSLog(#" 2.3 - ||| ----- -------- -----------> %#",*image);
dowloadImageBlock(error,downloadImg,urlImage,image);
});
}
You have missanderstanding in working with pointers.
It's should be:
*image = imageInDict;
Also you download image asynchroniously, and yours variable located in function call stack is already destroyed, when you try assign value to it. You should better use UIImageView* or some other objective-c class that have UIImage* in properties instead UIImage**