Set NSString with returned JSON value - ios

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"];

Related

imageView blank when set with URL?

I'm using the below to set my imageView with a url (located in path). Yes, the URL data is returned successfully, but for some reason, my imageView remains blank (just white?)
And yes, I've hooked up my imageView property... Any idea what's wrong? Should I be using a different block of code to accomplish this?
Viewcontroller.m
NSMutableDictionary *viewParamsDogs = [NSMutableDictionary new];
[viewParamsDogs setValue:#"mydogs" forKey:#"view_name"];
[DIOSView viewGet:viewParamsDogs success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.dogData = [responseObject mutableCopy];
[operation responseString];
NSDictionary *dic = [responseObject valueForKey: #"field_pet_photo_path"];
NSArray *arr = [dic valueForKey: #"und"];
NSDictionary *dic2= [arr objectAtIndex : 0];
NSString *path = [NSString stringWithFormat:#"%#", [dic2 valueForKey: #"safe_value"]];
NSLog(#"This is path %#", path);
if([path length]>0) {
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.dogimageView.image = image;
} else {
NSString *ImageURL = #"http://url.ca/paw.png";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.dogimageView.image = [UIImage imageWithData:imageData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
Path:
[5111:1673330] This is path (
"http://url.com/default/files/stored/1460659054.jpg"
)
NSLog(#"This is path %#, %#", path, NSStringFromClass(path.class)); returns:
2016-04-14 13:18:39.590 [5225:1700657] This is path (
"http://url.com/default/files/stored/1460659054.jpg"
), __NSCFString
I recommend usage of AFNetworking https://github.com/AFNetworking/AFNetworking for all networking connect features.
Import UIImageView+AFNetworking.h at beginning of file
#import "UIImageView+AFNetworking.h"
Get path from dic2
NSString *path = dic2[#"safe_value"];
Check if path is a string
if (![path isKindOfClass:[NSString class]]) {
return;
}
Create a NSURL object from string
NSURL *imageUrl = [NSURL URLWithString:path];
Set imageUrl to UIImageView
[self.dogimageView setImageWithURL:imageUrl];
You could check the full code in my gist https://gist.github.com/MaciejGad/fa8cb80dfc73ea55edeedb75418ea2ec
Edit:
the reason of error was the path that was set as:
NSString *path = #"(
\"http://url.com/default/files/stored/1460659054.jpg\"
)";
to change to normal URL we need to trim it:
NSMutableCharacterSet *characterSetToTrim = [NSMutableCharacterSet characterSetWithCharactersInString:#"()\""];
[characterSetToTrim formUnionWithCharacterSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
path = [path stringByTrimmingCharactersInSet:characterSetToTrim];
after this trimming path should be http://url.com/default/files/stored/1460659054.jpg
Try like this,
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.dogimageView.image = [[UIImageView alloc] initWithImage:image];
and You can use great library SDWebImage for caching image. When image comes from server use of this library is very helpful. Hope this will work.
Update :
NSString *path = [NSString stringWithFormat:#"%#", [dic2 valueForKey: #"safe_value"]];
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.dogimageView.image = [[UIImageView alloc] initWithImage:image];
Try this. :)
Try using dataWithContentsOfURL:options:error: instead and look if there is any error message there

Null value causing crash even with if/else statement?

I'm having the strangest issue. I'm using the below code to display the profile photo of a logged in user (I'm retrieving the image from a field in my Drupal database).
.m
//USER PHOTO
NSDictionary *user = [[DIOSSession sharedSession] user];
NSString *secondLink = user[#"field_photo_path"][#"und"][0][#"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];
self.imageView.image = [[UIImage alloc] initWithData:imageData];
} else {
NSString *ImageURL = #"http://url.com/default.png";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.imageView.image = [UIImage imageWithData:imageData];
}
Naturally, if secondLink is null (or empty, e.g. no photo has been uploaded), I receive the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArray0
objectForKeyedSubscript:]: unrecognized selector sent to instance
0x14f602fe0'
I thought I solved this issue with the if/else statement, but apparently not. How can I fix this?
Cheers!
NSString *secondLink = user[#"field_photo_path"][#"und"][0][#"safe_value"];
You need to verify that the user dictionary is valid before reading that far into it.
if (user[#"field_photo_path"]) {
// you can look for [#"und"] here
// providing it is a dictionary and not an array
if([user[#"field_photo_path"] isKindOfClass:[NSDictionary class]]){
if (user[#"field_photo_path"][#"und"]) {
// etc
}
}
}
You can reduce this nested code by modelling a User class as an NSObject subclass and include methods in that class to parse this data safely, allowing you to only write this validation code in one place.
Edit
As mentioned in a comment:
If the data in user[#"field_photo_path"][#"und"] is an NSDictionary and not an NSArray you cannot access it with [0] and will get your crash. You access NSArray's with an index (array[0], array[1] etc) and an NSDictionary with a key (dict[#"name"], dict[#"und"] etc)
Solution is to put check on on your key's
//USER PHOTO
NSDictionary *user = [[DIOSSession sharedSession] user];
if (user[#"field_photo_path"]) {
if ([user[#"field_photo_path"] isKindOfClass:[NSDictionary class]]) {
if (user[#"field_photo_path"][#"und"]) {
if ([user[#"field_photo_path"][#"und"]isKindOfClass:[NSArray class]]) {
if ([user[#"field_photo_path"][#"und"] count]>0) {
if (user[#"field_photo_path"][#"und"][0][#"safe_value"]) {
if ([user[#"field_photo_path"][#"und"][0][#"safe_value"] isKindOfClass:[NSDictionary class]]){
NSString *secondLink = user[#"field_photo_path"][#"und"][0][#"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];
self.imageView.image = [[UIImage alloc] initWithData:imageData];
} else {
NSString *ImageURL = #"http://url.com/default.png";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.imageView.image = [UIImage imageWithData:imageData];
}
}
}
}
}
}
}
}
You can also use try catch block to avoid crashing
#try {
//USER PHOTO
NSDictionary *user = [[DIOSSession sharedSession] user];
NSString *secondLink = user[#"field_photo_path"][#"und"][0][#"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];
self.imageView.image = [[UIImage alloc] initWithData:imageData];
} else {
NSString *ImageURL = #"http://url.com/default.png";
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
self.imageView.image = [UIImage imageWithData:imageData];
}
}
#catch (NSException *exception) {
//Handle expecption
}
#finally {
}

Converting from Binary to NSData and to Image

I am trying to convert binary to NSData, and I am able to get data but uiimage is still nil. Below is my code. Please can anyone help me on this.
NSData *data = [self dataFromBase64EncodedString:[dictionary objectForKey:#"object"]];
UIImage *image = [UIImage imageWithData:data];
-(NSData *)dataFromBase64EncodedString:(NSString *)string{
if (string.length > 0) {
NSString *data64URLString = [NSString stringWithFormat:#"data:;base64,%#", string];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:data64URLString]];
return data;
}
return nil;
}
Your url seems to be missing the base url.
NSString *data64URLString = [NSString stringWithFormat:#"data:;base64,%#", string];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:data64URLString]];
Based on the above.. the url is set to "data:;base64,
shouldnt it be something like "http://my.server.com/imageurl"

App crashes if null image URL is loaded in JSON object

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"];
}

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