How to get array of values from NSDictionary array - ios

When I try to print array of json values in log, I get addresses instead of values. Here's how I coded.
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:jsonArray.count];
NSMutableArray *anotherTempArray = [NSMutableArray arrayWithCapacity:jsonArray.count];
NSDictionary *dict;
for(dict in jsonArray)
{
NSString *projectName = dict[#"Name"];
NSString *urlText = dict[#"Url"];
NSLog(#"Url text in array = %#", urlText);
NSString *attch = dict[#"attachmentes"];
NSLog(#"Attached url in array = %#", attch);
NSString *projID = dict[#"ProjectID"];
NSLog(#"Project ID in array = %#", projID);
SaveAttachment *saveAt = [[SaveAttachment alloc] initWithName:projectName withList:#"View" withAttachment:#"View"];
[tempArray addObject:saveAt];
SaveProjectId *saveProj = [[SaveProjectId alloc] initWithProjectId:projID];
saveProj.projectId = projID;
[anotherTempArray addObject:saveProj];
}
array = tempArray;
[self.tableViewProject reloadData];
NSLog(#"Array of project IDs === %#", anotherTempArray); //Get values (array of project ids here.
}

Replace
SaveProjectId *saveProj = [[SaveProjectId alloc] initWithProjectId:projID];
saveProj.projectId = projID;
[anotherTempArray addObject:saveProj];
with
[anotherTempArray addObject:projID];

This is because your anotherTempArray contains objects of SaveProjectId ie, everytime in for loop you are adding saveProj object not projID. Thats why your array showing SaveProjectId objects.
If you want to directly save them, then use the below modification
[anotherTempArray addObject:projID];
or you can use like(this is i would prefer)
NSLog(#"First project ID === %#", [anotherTempArray objectAtindex:0] projectId]);

You are storing SaveProjectId objects in the array, therefore when you print the content you see the address of those objects.

your "anotherTemoArray" is having objects of SaveProbectId so you have to pass object at index to SaveProjectId and then you can see the array information

When calling NSLog(#"Array of project IDs === %#", anotherTempArray); the -(NSString*)description method on each of the objects inside 'anotherTempArray' is being called.
In your case that means -(NSString*)description is being called on SaveProjectId objects. Override it to print out what you want... e.g.
-(NSString*)description {
return [NSString stringWithFormat:#"SaveProjectId: %#",self.projectId];
}

Related

Convert Array of Dictionary in single Array

This code:
server_response = [{id:1},{id:2},{id:3},{id:4}]
I am getting above response from server now I want only the list of ids in one array like
ids = [1,2,3,4];
I know we can do by for loop but it takes long time if thousand of ids inside the response array.
Is there any better way to achieve above equation?
NSArray *result = [yourArray valueForKey:#"id"]
From the documentation for NSArray instance method valueForKey:
Returns an array containing the results of invoking valueForKey: using key on each of the array's objects
NSMutableArray *resultArray = [NSMutableArray array];
for (NSDictionary *dict in server_response) {
[resultArray addObject:[dict objectForKey:#"id"]];
}
Try above code. Hope it will help you. Result array has final values
NSArray *server_response = #[#{#"id":#"1"},#{#"id":#"2"},#{#"id":#"3"},#{#"id":#"4"}];
NSMutableArray *resultArray = [NSMutableArray array];
NSString *birdtemp;
for (NSDictionary *object in server_response) {
birdtemp = object[#"id"];
[resultArray addObject:birdtemp];
}
NSLog(#"%#",resultArray);
OutPut: [
1,
2,
3,
4
]

Remove entries from NSMutableDictionary based on match on NSString value

After a network call to the Instagram API, I get back a responseDictionary NSDictionary delegate with the following Key/Value structure:
{
data = (
{
bio = "Los Angeles/Orange County Realtor\U00ae \n\U6d1b\U6749\U77f6\U623f\U5730\U4ea7\U7ecf\U7eaa\U4eba\nCall/Text/WhatsApp: (310) 717-1321\nEmail: Jxxxcom\nWeChat (\U5fae\U4fe1): xx";
"full_name" = "xx yy (\U7530\U4f73\U6dfc) Rx Realty";
id = 25354408;
"profile_picture" = "http://scontent-a.cdninstagram.com/hphotos-xpa1/outbound-distillery/t0.0-20/OBPTH/profiles/profile_xxx_75sq_1391378894.jpg";
username = jxxi;
website = "http://www.Jxghty.com";
},
The profile_picture key often has an NSString value that contains anonymousUser (for the users who didn't set any profile pictures).
I am looking to remove those entries from my responseDictionary as follows:
//Create mutable copy of IG responseDictionary
NSMutableDictionary *dictCleanAvatars = [responseDictionary mutableCopy];
NSLog(#"Log dictCleanAvatars after mutableCopy IG response: %#", dictCleanAvatars);
NSArray *keys = [dictCleanAvatars allKeys]; //get all the keys
NSUInteger k2 = [dictCleanAvatars count];
NSLog(#"k2 in dictCleanAvatars before cleanup is: %lu", (unsigned long)k2);
for (int i = 0; i<k2; i++)
{
if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isKindOfClass:[NSString class]])
{
//if its an NSString - don't want an exception if its another type of object
NSLog(#"Yes, objectAtIndex:i us Kind ofClass NSString for i = %d", i);
if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] rangeOfString:#"anonymousUser"].location != NSNotFound)
{
NSLog(#"Yes, anonymousUser identified in objectAtIndex:i for i = %d", i);
//if object has the key word im looking for
[dictCleanAvatars removeObjectForKey:[keys objectAtIndex:i]]; //remove the key
NSLog(#"That's dictCleanAvatars after loop %d: %#", i, dictCleanAvatars);
}
}
}
But this doesn't work.
Would value feedback from more experience iOS developers.
If you're trying to build an array that includes everything from the data key's array, but omitting those dictionaries for which profile_picture contains the string "AnonymousUser", you can use NSPredicate:
NSArray *dataArray = responseDictionary[#"data"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"not (profile_picture contains 'AnonymousUser')"];
NSArray *filteredArray = [dataArray filteredArrayUsingPredicate:predicate];
Or you can use predicateWithBlock:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject[#"profile_picture"] rangeOfString:#"AnonymousUser"].location == NSNotFound;
}];
BTW, if you already have a mutable array, you can also remove entries from it using filterUsingPredicate, using the above predicates:
NSMutableArray *mutableDataArray = [responseDictionary[#"data"] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"not (profile_picture contains 'AnonymousUser')"];
[mutableDataArray filterUsingPredicate:predicate];
If, on the other hand, you don't want to remove entire dictionaries from the array of dictionaries, but rather want to simply remove the occurrences of profile_picture for which "AnonymousUser" is present, you want to ensure that not only is the array mutable, but so are its constituent dictionaries.
The easiest way of doing this is to specify the NSJSONReadingMutableContainers option when parsing the JSON. Then you can just iterate through the NSMutableDictionary entries, removing the profile_picture entries with a profile_picture with "AnonymousUser" in them:
NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error];
NSMutableArray *mutableDataArray = responseDictionary[#"data"];
for (NSMutableDictionary *dictionary in mutableDataArray) {
NSString *profilePicture = dictionary[#"profile_picture"];
if ([profilePicture rangeOfString:#"AnonymousUser"].location != NSNotFound) {
[dictionary removeObjectForKey:#"profile_picture"];
}
}
If, however, you can't specify the NSJSONReadingMutableContainers option when you parse the JSON and are stuck with a immutable collection, you need to make a mutable copy of it. Unfortunately, a simple mutableCopy of the array won't make the member dictionaries mutable themselves, but you can use a Core Foundation call to CFPropertyListCreateDeepCopy to make a mutable array with mutable entries, which you can then modify:
NSMutableArray *mutableDataArray = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)responseDictionary[#"data"], kCFPropertyListMutableContainers));
Then you can use the above for loop, iterating through this array's dictionary entries, removing the offending profile_picture entries.
if [[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isEqualToString#"anonymousUser"] {
The problem is, suppose [dictCleanAvatars objectForKey:[keys objectAtIndex:i]] is not an NSString? You might want to check for that first.
If the only field you are looking at is profile_picture, I would go with a less generic approach which is much more readable and understandable
This code works for me
- (void)testExample
{
NSDictionary *dictionary = #{ #"data": #[ #{ #"bio": #"blah blah", #"profile_picture": #"some stuff anonymousUser other stuff" },
#{ #"bio": #"some other object", #"profile_picture": #"some other profile picture link" }] };
// dictionary is a mock of the data you provided
NSArray *data = [dictionary objectForKey:#"data"];
for (NSDictionary * avatarDict in data) {
NSMutableDictionary *mdict = [avatarDict mutableCopy];
id ppid = [mdict objectForKey:#"profile_picture"];
if ([ppid isKindOfClass:[NSString class]]) {
NSString *pp = (NSString *)ppid;
if ([pp rangeOfString:#"anonymousUser"].location != NSNotFound) {
[mdict removeObjectForKey:#"profile_picture"];
}
}
NSLog(#"altered dictionary: %#", mdict);
}
}
Output:
2014-08-13 10:53:36.727 test[11981:60b] altered dictionary: {
bio = "blah blah";
}
2014-08-13 10:53:36.728 test[11981:60b] altered dictionary: {
bio = "some other object";
"profile_picture" = "some other profile picture link";
}

NSDictionary allKeysForObject in an array

I have a NSDictonary that looks like this. I need to get all the key values that are associated for a particular name. For example the name Samrin is associated with keys 11.titleKey, 110.titleKey and so on. The problem I have is that I am not sure how can I get to the object in an array and then pass they key value back?
I tried the following code with not much success.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *stringsPlistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"birthdays.plist"];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:stringsPlistPath];
NSArray *temp = [dictionary allKeysForObject:#"Samrin Ateequi"];
NSLog(#"temp: %# ...", temp);
OUTPUT:
temp: (
) ...
I think you can use keysOfEntriesPassingTest for that. Something like:
NSSet *keysSet = [dictionary keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
if ([[obj objectAtIndex:0] isEqualToString:#"Samrin Ateequi"]) {
return YES;
} else {
return NO;
}
}];
allKeysForObject: looks through the dictionary for values equal to that object using isEqual:. Your values for that dictionary are NSArrays, so it will never match the NSString you are looking for.
If you don't change the data structure you will have to loop through everything to get the results you need.
If you are willing to upgrade to Core Data with an SQL store, then your results will be fast and the code will be easier than looping through the dictionary. This is the kind of problem that Core Data was meant to solve. You can get started with the Core Data Programming Guide.
Hope this will help you: I have taken an example.
NSDictionary *dict = #{#"key1":#[#"mania",#"champ"],
#"key2":#[#"mann",#"champ"],
#"key3":#[#"mania",#"champ",#"temp"]};
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"ANY SELF=%#",#"mania"];
NSArray *allValues = [dict allValues];
NSArray *requiredRows = [allValues filteredArrayUsingPredicate:filterPredicate];
NSMutableArray *requiredKeyArray = [[NSMutableArray alloc]initWithCapacity:0];
for (id anObj in requiredRows) {
[requiredKeyArray addObject:[dict allKeysForObject:anObj]];
}
NSLog(#"Desc: %#",[requiredKeyArray description]);

Search element in nsdictionary by value

I have nsdictionary which contains elements with following structure
name --> value
email--> key
I get value(of above structure) from user,
now I want to search element in nsdictionary by value(entered by user) not by key, whether it is present in nsdictionary or not and also want to get index of that element if present.
How to do this?
The best to do so would propably be
- (NSArray *)allKeysForObject:(id)anObject
This method of NSDictionary gives you back all the keys having anObject as their value. If you only have each object once in the whole dictionary it will logically return an array with only one key in it.
NSArray * users = ...; //your array of NSDictionary objects
NSPredicate *filter = [NSPredicate predicateWithFormat:#"email = test#gmail.com"];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:filter];
for more than one value of email, then use an OR in the predicate:
filter = [NSPredicate predicateWithFormat:#"contact_type = 42 OR contact_type = 23"];
The dictionary data structure has no 'order', so you'd have to search for your key by iterating the collection and looking for the desired value.
Example:
NSString *targetKey = nil;
NSArray *allKeys = [collection allKeys];
for (int i = 0; i < [allKeys count]; ++i) {
NSString *key = [allKeys objectAtIndex:i];
NSString *obj = [collection objectForKey:key];
if ([obj isEqualToString:searchedString]) { // searchedString is what you're looking for
targetKey = key;
break;
}
}
// check if key was found (not nil) & proceed
// ...
You can search the entered value in NSDictionary , but you can't get an index of value , as NSDictionary has no order of key value pair.
NSArray *array = [yourDictionaryObject allValues];
if ([array containsObject:#"userEnteredValue"]) {
<#statements#>
}
You need to iterate through the Dictionary for the keys has the Value of your need:
Try this:
NSArray *keys= [json allKeys];
for (NSString *keysV in keys){
NSLog(#"Keys are %#", keysV);
if([Your_Dict objectForKey: keysV] isEqual:#"string to Match"){
//Do your stuff here
}
}

how to add JSON data to an NSArray

I have json data as below.
[
{"id":"2","imagePath":"image002.jpg","enDesc":"Nice Image 2"},
{"id":"1","imagePath":"image001.jpg","enDesc":"Nice Image 1"}
]
I am assigning this to variable named NSArray *news.
Now I have three different array as below.
NSArray *idArray;
NSArray *pathArray;
NSArray *descArray;
I want to assign data of news to these arrays so that finally I should have as below.
NSArray *idArray = #["2","1"];
NSArray *pathArray = #["image002.jpg","image001.jpg"];
NSArray *descArray = #["Nice Image 2","Nice Image 1"];
Any idea how to get this done?
With the help of below answer this is what I did.
pathArray = [[NSArray alloc] initWithArray:[news valueForKey:#"imagePath"]];
I don't wanted to use NSMutableArray for some reasons.
You should use JSONKit or TouchJSON to convert your JSON data to Dictionary.
Than you may do this :
NSArray *idArray = [dictionary valueForKeyPath:#"id"]; // KVO
Use this
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:receivedData options:NSJSONReadingMutableContainers error:nil];
then you can extract all the information that you need from there you have NSArray that contains NSDictionary , where you can go and use objectForKey: to get all the info you need.
Load the json data into an NSDictionary, which you may call "news" . Then retrieve as
NSArray *idArray = [news valueForKeyPath:#"id"];
NSArray *pathArray = [news valueForKeyPath:#"imagePath"];
NSArray *descArray = [news valueForKeyPath:#"enDesc"];
Yes all the above ans is correct I am just integrating all of them together to be easly use to you:
NSArray *serverResponseArray = [NSJSONSerialization JSONObjectWithData:receivedData options:NSJSONReadingMutableContainers error:nil]; // I am assigning this json object to an array because as i show it is in array format.
now:
NSArray *idArray = [[NSMutableArray alloc] init];
NSArray *pathArray = [[NSMutableArray alloc] init];
NSArray *descArray = [[NSMutableArray alloc] init];
for(NSDictionary *news in serverResponseArray)
{
[idArray addObject:[news valueForKey:#"id"]];
[pathArray addObject:[news valueForKey:#"imagePath"]];
[descArray addObject:[news valueForKey:#"enDesc"]];
}

Resources