App crashes if null image URL is loaded in JSON object - ios

I am populating a tableView with objects from a MySQL table via JSON.
The source data are introduced by many users in a web site form, and sometimes they don't introduce an image URL into a field.
The downloaded JSON object are shown in the tableView which rows are configured to show text, detail text and image.
If the object doesn't have an image URL, the app crashes, and I want to show a default image instead, to avoid the crash.
This is how am I loading the JSON data for the object's image:
NSMutableString *logo = [[NSMutableString alloc]initWithString:#"http://mujercanariasigloxxi.appgestion.eu/logos/"];
NSString *imageURL = [[categorias objectAtIndex:indexPath.row] objectForKey:#"strImagen"];
[logo appendString:imageURL];
NSURL *logoURL = [NSURL URLWithString:logo];
NSData *logoData = [NSData dataWithContentsOfURL:logoURL];
cell.imageView.image = [UIImage imageWithData:logoData];
What should be the best way to avoid the crash and to show a default image if the web site user doesn't include an image URL in the web form?

Try use a if-else condition, like
NSMutableString *logo = [[NSMutableString alloc]initWithString:#"http://mujercanariasigloxxi.appgestion.eu/logos/"];
NSData *logoData;
if([categorias objectAtIndex:indexPath.row] && [[categorias objectAtIndex:indexPath.row] objectForKey:#"strImagen"]){
NSString *imageURL = [[categorias objectAtIndex:indexPath.row] objectForKey:#"strImagen"];
[logo appendString:imageURL];
NSURL *logoURL = [NSURL URLWithString:logo];
logoData = [NSData dataWithContentsOfURL:logoURL];
}
else {
//load your default image here
logoData = //default logo data
}
cell.imageView.image = [UIImage imageWithData:logoData];

//set an activity indicator
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSString *imageURL = [[categorias objectAtIndex:indexPath.row] objectForKey:#"strImagen"];
if (imageURL.count>0){
[logo appendString:imageURL];
//declare logodata as nsdata
logoData=[NSData dataWithContentsOfURL:[NSURL URLWithString:logo]];
}
dispatch_sync(dispatch_get_main_queue(), ^{
//turn the activity indicator off
if(logoData!=nil)
cell.imageView.image = [UIImage imageWithData:logoData];
else
//set your default image.
});
});
Hope this might help you.

You may try checking whether imageurl is nil or in some cases it will come as null.
NSMutableString *logo = [[NSMutableString alloc]initWithString:#"http://mujercanariasigloxxi.appgestion.eu/logos/"];
NSString *imageURL = [[categorias objectAtIndex:indexPath.row] objectForKey:#"strImagen"];
if(imageURL != nil && ![imageURL isEqual:[NSNull null]])
{
[logo appendString:imageURL];
NSURL *logoURL = [NSURL URLWithString:logo];
NSData *logoData = [NSData dataWithContentsOfURL:logoURL];
cell.imageView.image = [UIImage imageWithData:logoData];
}
else{
cell.imageView.image = [UIImage imageNamed:#"Default_image"];
}

Related

Need to set the image from URL without any blink. Read the description to know the complete scenario

I am uploading the image from the ImagePicker and once the image is upload on the server I show it from URL. So from local image to URL image, there comes a blink, which I want to avoid but I am unable to fix it. Any suggestion will be really helpful. I am adding the code below:
- (void)setDataOnCell:(NSDictionary *)dict {
self.messageTimeLabel.text = [CommonUtils checkForNUllValue:[dict valueForKey:#"msg_time"]];
if (![[CommonUtils checkForNUllValue:[dict valueForKey:#"msg_status"]] isEqualToString:#"Read"]) {
self.messageTickImageView.image = [UIImage imageNamed:#"check_delivered_icon"];
self.messageStatusLabel.textColor = [UIColor colorWithRed:166.0f/255.0f green:166.0f/255.0f blue:166.0f/255.0f alpha:1.0];
}
else {
self.messageTickImageView.image = [UIImage imageNamed:#"check_read_icon"];
self.messageStatusLabel.textColor = [UIColor colorWithRed:254.0f/255.0f green:223.0f/255.0f blue:224.0f/255.0f alpha:1.0];
}
self.messageStatusLabel.text = [CommonUtils checkForNUllValue:[dict valueForKey:#"msg_status"]];
if ([[NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment_type"]] isEqualToString:#"local_img"]){
self.messageImageview.image = [dict valueForKey:#"attachment"];
}
else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#", [NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment"]]]];
NSData *urlData = [NSData dataWithContentsOfURL:imageURL];
//This is your completion handler
dispatch_sync(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:urlData];
self.messageImageview.image = image;
});
});
}
}
first of all you need to set a default image on this image view after that you call image by url and set on this
NSOperationQueue *queueThumbnl = [[NSOperationQueue alloc] init];
[queueThumbnl setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
[queueThumbnl addOperationWithBlock:^{
// Background work
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#", [NSString stringWithFormat:#"%#", [dict valueForKey:#"attachment"]]]];
NSData *urlData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:urlData];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.messageImageview, #"messageImageview", urlData, #"imageData", nil];
[self performSelectorOnMainThread:#selector(mainThreadUIUpdate:) withObject:dict waitUntilDone:YES];
// [self updateThumbnailOnMainThread:anItem setImageTo:cell];
}];
-(void)mainThreadUIUpdate:(NSDictionary *)dict
{
UIImageView *messge = [dict objectForKey:#"messageImageview"];
UIImage *image = [dict objectForKey:#"image"];
[messge.imageView setImage:image];
[cell.imageView setNeedsDisplay:YES];
}

Set NSString with returned JSON value

I'm trying to set my imageView with the url returned in the JSON data below in "value" (secondLink). When I use the following code, it returns the entire block in JSON through my XCode console - what should my code look like if I ONLY want the image's URL to be returned (right now, I assume it's trying to set the imageView with EVERYTHING returned in secondLink)?
ViewController.m
NSString *secondLink = [[[[DIOSSession sharedSession] user] objectForKey:#"field_photo_path"] objectForKey:#"safe_value"];
NSLog(#"This is second link %#", secondLink);
if([secondLink length]>0) {
NSString *ImageURL = secondLink;
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.imageView.image = [UIImage imageWithData:imageData];
} else {
NSString *ImageURL = #"defaulturl.com";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.imageView.image = [UIImage imageWithData:imageData];
}
JSON data
{
und = (
{
format = "<null>";
"safe_value" = "http://myurl.com/sites/default/files/stored/photo.jpg";
value = "http://myurl.com/sites/default/files/stored/photo.jpg";
}
);
}
In field_photo_path there is a dictionary und which contains an array.
The first item in the array is a dictionary containing the key safe_value.
It assumes that user is also a dictionary (at least it responds to objectForKey:)
NSDictionary *user = [[DIOSSession sharedSession] user];
NSString *secondLink = user[#"field_photo_path"][#"und"][0][#"safe_value"];

How can get any message if Image View can't get image from given URL?

I am fetching URL from web, and I want to show any message if image view can't get image from given URL.
Here is my Code.
NSString * image1 = [WebArray objectForKey:#"image_url"];
NSString * image2 = [[tempArray objectAtIndex:0]objectForKey:#"user_image"];
dispatch_queue_t imageQueue = dispatch_queue_create("Image Queue", NULL);
dispatch_async(imageQueue, ^{
NSURL *url = [NSURL URLWithString:image1];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
NSURL *url1 = [NSURL URLWithString:image2];
NSData *imageData1 = [NSData dataWithContentsOfURL:url1];
UIImage *image11 = [UIImage imageWithData:imageData1];
dispatch_async(dispatch_get_main_queue(), ^{
[user_image setImage:image];
[self.tag_user_img setImage:image11];
});
});
check image view is empty or not using
if(CGSizeEqualToSize(imageView.image.size, CGSizeZero))
{
show alert here....
}
dispatch_async(dispatch_get_main_queue(), ^{
if(!image)
{
// show your message
}
else
{
[user_image setImage:image];
}
});

Downloading image from a url into a UIImageVIew dynamically

I am trying to insert and image into a UIImageView from a url. I used the following code to do so.
When running the program gets stuck at
NSURL *url = [NSURL URLWithString:urlstring];
In the below code and it shows "Thread 1 : signal SIGABRT" on that particular line.
Can someone help me with this and tell if the format that i used is correct or what i had did wrong??
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newoffer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *temp = [product objectAtIndex:indexPath.row];
UILabel *Label = (UILabel *)[cell viewWithTag:201];
Label.text = [temp objectForKey:#"item_name"];
UIImageView *Image = (UIImageView *)[cell viewWithTag:200];
NSString *urlstring=[temp objectForKey:#"image_url"];
NSURL *url = [NSURL URLWithString:urlstring];
NSData *data = [NSData dataWithContentsOfURL:url];
Image.image = [UIImage imageWithData:data];
return cell;
}
Change this code:
NSURL *url = [NSURL URLWithString:urlstring];
NSData *data = [NSData dataWithContentsOfURL:url];
Image.image = [UIImage imageWithData:data];
To:
dispatch_queue_t myqueue = dispatch_queue_create("myqueue", NULL);
// execute a task on that queue asynchronously
dispatch_async(myqueue, ^{
NSURL *url = [NSURL URLWithString:[urlstring stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];;
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
Image.image = [UIImage imageWithData:data]; //UI updates should be done on the main thread
});
});
As mentioned by others, an Image Caching library like SDWebImage will help a lot because even with this implementation, you just push the download process to a background thread so the UI does not get stucked, but you are not caching anything.
Try this
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.vbarter.com/images/content/1/9/19517.jpg"]]]];
For async downloading
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.vbarter.com/images/content/1/9/19517.jpg"]]]];
});
if url is dynamic then
NSString *stringUrl; // this can be any valid url as string
[image setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:stringUrl]]]];
NSData *data = [NSData dataWithContentsOfURL:url];
will load imageData synchronous, that means main thread will be blocked .
Use the project on github:SDWebImage for image asynchronous loading and cache.
There's probably better libraries that do this now, but I have always been using this for my projects and it works well: AsyncImageView. There are other alternatives like SDWebImage
But basically, you don't want to use
NSData *data = [NSData dataWithContentsOfURL:url];
because it will block the main thread until the image is downloaded. To avoid this you might want to use something asynchronous, like the above two libraries.
For example, with AsyncImageView, it becomes as easy as:
myImageView.imageURL = someNSURL;

NSData dataWithContentsOfURL for twitter picture returning nil when same thing works for instagram

Im trying to display twitter pictures but dataWithContentsOfString is returning nil when the same exact thing works for an instagram photo url. It works when I use the actual url instead of getting it from the nsdictionary
NSString *twitterString = #"http://pbs.twimg.com/media/BYWHiq1IYAAwSCR.jpg"
but not like this
if ([post valueForKeyPath:#"entities.media.media_url"]) {
NSString *twitterString = [NSString stringWithFormat:#"%#", [post valueForKeyPath:#"entities.media.media_url"]];
NSURL *twitterPhotoUrl = [NSURL URLWithString:twitterString];
dispatch_queue_t queue = kBgQueue;
dispatch_async(queue, ^{
NSData* data = [NSData dataWithContentsOfURL:twitterPhotoUrl];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
[streamPhotoArray replaceObjectAtIndex:indexPath.row withObject:image];
cell.twitterPhoto.image = image;
});
});
}

Resources