So! I have an NSDictionary that's pulling json out of my database just fine. I also have a mutable array that creates items for my beautiful SESpringboard view. The problem is that, initially, I only had a few items, so I was creating each item manually. But now that I have THOUSANDS of items I want to do something like a "while" loop in php that would just keep creating items until it goes through the whole table.
Here's the code I've got:
Goods *g = [[Goods alloc] init];
g.GID = [dict objectForKey:#"id"];
g.GName = [dict objectForKey:#"name"];
NSLog(#"bk:%#",g.GName);
g.GImg = [dict objectForKey:#"image"];
g.GDesc = [dict objectForKey:#"description"];
NSMutableArray *items = [NSMutableArray array];
[items addObject:[SEMenuItem initWithTitle:g.GName imageName:g.GImg viewController:self removable:NO]];
SESpringBoard *thunderboard = [SESpringBoard initWithTitle:#"Boom" items:items launcherImage:[UIImage imageNamed:#"thor.png"]];
This works absolutely fine… except that what it does is place all the names and all the images one on top of another instead of creating a new item for each result.
If this were php I'd do something like "g.items" and it would just create a new item for each "g" but I'm not sure what to do here. Any help would be appreciated. (I googled but couldn't find anything like this for SESpringBoard items…)
Assuming you parse your json in a variable named allGoods, and that it's an array containing dictionaries representing your "Goods" objects.
You can do this:
NSMutableArray *items = [NSMutableArray array];
for (NSDictionary *dictionary in allGoods) {
[items addObject:[SEMenuItem initWithTitle:[dictionary objectForKey:#"name"] imageName:[dictionary objectForKey:#"image"] viewController:self removable:NO]];
}
SESpringBoard *thunderboard = [SESpringBoard initWithTitle:#"Boom" items:items launcherImage:[UIImage imageNamed:#"thor.png"]];
I removed your usage of "Goods *g", as it looks like you don't need to keep a reference to such an object.
EDIT: here is the 5 items limit you requested
The "MIN" in the for loop is just in case allGoods contains less than 5 items.
for (int i = 0; i < MIN(5, allGoods.count); i++) {
NSDictionary *dictionary = [allGoods objectAtIndex:i];
[items addObject:[SEMenuItem initWithTitle:[dictionary objectForKey:#"name"] imageName:[dictionary objectForKey:#"image"] viewController:self removable:NO]];
}
SESpringBoard *thunderboard = [SESpringBoard initWithTitle:#"Boom" items:items launcherImage:[UIImage imageNamed:#"thor.png"]];
Related
I am not sure what I am missing but i have this for loop below. When I loop through it, the dictionary object gets added to the array like it should each time. But for some reason the next time it loops, it completely replaces all the dictionary object values with the current dictionary value it is looping. So for example I have 5 dictionary objects in my array when it's done looping and all of them have the latest loop values...
NSMutableArray *events = [NSMutableArray array];
NSMutableDictionary *event = [[NSMutableDictionary alloc]init];
NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"Update"]];
for (int i = 0; i < [array count]; i = i + 2){
[event setValue:[array objectAtIndex:i+1] forKey:#"Event-Type"];
[event setValue:[array objectAtIndex:i] forKey:#"date"];
[events addObject:event];
}
You would have to allocate a new NSMutableDictionary each iteration of the loop, either at the beginning of each loop (i.e. just move that line into the loop) or when you do addObject you can copy the dictionary using [NSDictionary dictionaryWithDictionary: event];
This is because NSMutableDictionary is an object; It is passed by reference. So you're just putting the same instance of NSMUtableDictionary into your array n times.
You can see this by logging the object at each index of your array at the end, and you can check the memory address to see they're all the same.
Arrays in objective C pass references, not copies. So when you call [events addObject:event] then write to that same event later it gets written over and added newly. Just move the creation of the dictionary inside the for loop and you should be good to go.
You need to alloc init your dictionary inside the loop and also note addition as per Apple Standard always use setObject: forKey: if you are using dictionary. Please refer the below code:-
NSMutableArray *events = [NSMutableArray array];
NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"Update"]];
for (int i = 0; i < [array count]; i = i + 2){
NSMutableDictionary *event = [[NSMutableDictionary alloc]init];
[event setObject:[array objectAtIndex:i+1] forKey:#"Event-Type"];
[event setObject:[array objectAtIndex:i] forKey:#"date"];
[events addObject:event];
}
I am working with an application in which i am getting photoID ,which is a string.
I am storing that photoID in array,and again add that array in another array.
Below iS the code::
NSString *photoID;
arr=[[NSMutableArray alloc]initWithCapacity:10];
array=[[NSMutableArray alloc] init];
[array addObject:photoID];
[arr arrayByAddingObjectsFromArray:array];
//number=(int)arr[1];
NSLog(#"arr : %#",arr);
NSLog(#"arr[0] : %#",arr[0]);
NSLog(#"arr[1] : %#",arr[1]);
NSLog(#"Number1 : %#",number1);
NSLog(#"Number : %d",number);
when i tried to access the value of arr[1],my application crashes.
i don't know what am i doing wrong.am i doing wrong to add strings in array,and truing to access unsaved data?
Please help me out.
Thanks in advance
It is because this line: [arr arrayByAddingObjectsFromArray:array]; does nothing to the arr, it only
Returns a new array that is a copy of the receiving array with the
objects contained in another array added to the end.
You should replace it with [arr addObjectsFromArray:array];. And also, you only have 1 element in arr which is at index 0, so the arr[1] should crash but arr[0] should work.
First array should be NSArray if you want to arrayByAddingObjectsFromArray or addObjectsFromArray
NSArray *array1=[[NSArray alloc]initWithObjects:#"1",#"2",#"3", nil];
NSMutableArray *array2=[[NSMutableArray alloc]init];
[array2 addObjectsFromArray:array1];
NSLog(#"%d",array2.count);
You can also use like this:
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithObjects:#"1",#"2",#"3", nil];
NSMutableArray *outerArray = [NSMutableArray array];
for(int i=0;i<=innerArray.count;i++)
{
[outerArray addObject:innerArray];
}
I have three NSArrays, and I want to combine them all into a single NSDictionary. The problem is that as I iterate through the arrays and create the dictionary, it overwrites the previous object. In the end I only have one object in my dictionary. What am I doing wrong? Here's my code:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(int i=0; i<[array0 count]; i++) {
[dict setObject:[array0 objectAtIndex:i]
forKey:#"one"];
[dict setObject:[array1 objectAtIndex:i] f
orKey:#"two"];
[dict setObject:[array2 objectAtIndex:i]
forKey:#"three"];
}
Maybe this will clarify what I mean...
this is the result I'm going for:
{one = array0_obj0, two = array1_obj0, three = array2_obj0},
{one = array0_obj1, two = array1_obj1, three = array2_obj1},
{one = array0_obj2, two = array1_obj2, three = array2_obj2},
etc
Thanks
Issue
You are inserting and replacing the same object at the specific key. So all what dictionary has is its last object at the last index.
Solution
Use this code to add the three arrays into one dictionary with your specific keys.
NSDictionary *yourDictinary = #{#"one": array0, #"two": array1, #"three": array3};
Edit
If you need to add objects of your NSMutableArrays to one NSDictionary you can follow the answer posted by #ElJay, but that's not a good practice, since you are dealing with multiple objects with unique keys.
Update
To do that thing, we are talking about a single NSMutableArray and multiple NSDictinarys.
Follow this code:
NSMutableArray *allObjects = [NSMutableArray new];
for(int i=0; i<[array0 count]; i++) {
dict = #{#"one": array0[i], #"two": array1[i], #"three": array2[i]};
[allObjects addObject:dict];
}
Here ya go:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for(int i=0; i<[array0 count]; i++) {
[dict setObject:[array0 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr0_%d", i]];
[dict setObject:[array1 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr1_%d", i]];
[dict setObject:[array2 objectAtIndex:i] forKey:[NSString stringWithFormat:#"arr2_%d", i]];
}
Edit - with revised question:
self.array0 = #[#"Array0_0",#"Array0_1",#"Array0_2", #"Array0_3"];
self.array1 = #[#"Array1_0",#"Array1_1",#"Array1_2", #"Array1_3"];
self.array2 = #[#"Array2_0",#"Array2_1",#"Array2_2", #"Array2_3"];
NSMutableArray *finalArray = [[NSMutableArray alloc] init];
for (int i=0; i< [_array0 count]; i++) {
NSDictionary *dict = #{#"one":[_array0 objectAtIndex:i], #"two":[_array1 objectAtIndex:i],#"three":[_array2 objectAtIndex:i]};
[finalArray addObject:dict];
}
NSLog(#"finalArray = %#", [finalArray description]);
You're reusing the keys ("one", "two" and "three") through each iteration of the loop. Keys in an NSDictionary have to be unique.
If you want many dictionary but only three keys, you should save each dict in an array.
We have an app that calls a SOAP web service and retrieves a long list of XML, which the app then parses into an NSArray of NSDictionary objects. The NSArray contains a list of Rental Apartment information, each of which is stored into an NSDictionary.
The entire list may contain 10 different types of Apartments (i.e. 2-room, 3-room), and we need to split the NSArray into smaller NSArrays based on Room-Type, which has the key "roomType" in the NSDictionary objects.
Currently our algorithm is
Use [NSArray valueForKeyPath:#"#distinctUnionofObjects.room-type"]
to obtain a list of unique room-type values.
Loop through the list of unique room-type values
For each unique room-type value, use NSPredicate to retrieve matching items from the Original list
Our code is below (renamed for clarity):
NSArray *arrOriginal = ... ...; // Contains the Parsed XML list
NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];
NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:#"distinctUnionOfObjects.roomType"];
for(NSString *strRoomType in arrRoomTypes) {
NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:#"roomType=%#", strRoomType];
NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType]; // TAKES A LONG TIME EACH LOOP-ROUND
[marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}
However, step 3 is taking a long time as the original list may contain large amount (>100,000) of items. It seems that NSPredicate goes through the entire list for each key value. Is there a more efficient way of splitting a large NSArray into smaller NSArrays, based on NSDictionary keys?
If the order of your splited Arrays is not important, i have a solution for you:
NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
id key = [dict valueForKey:#"roomType"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];
This is quite performant
- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
NSMutableDictionary *groupedItems = [NSMutableDictionary new];
for (id item in array) {
id <NSCopying> key = keyForItemBlock(item);
NSParameterAssert(key);
NSMutableArray *arrayForKey = groupedItems[key];
if (arrayForKey == nil) {
arrayForKey = [NSMutableArray new];
groupedItems[key] = arrayForKey;
}
[arrayForKey addObject:item];
}
return groupedItems;
}
Improving #Jonathan answer
Converting array to dictionary
Maintaining the same order as it was in original array
//only to a take unique keys. (key order should be maintained)
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init];
NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary];
for (NSDictionary *eachDict in arrOriginal) {
//Collecting all unique key in order of initial array
NSString *eachKey = [eachDict objectForKey:#"roomType"];
if (![aMutableArray containsObject:eachKey]) {
[aMutableArray addObject:eachKey];
}
NSMutableArray *tmp = [grouped objectForKey:key];
tmp = [dictFromArray objectForKey:eachKey];
if (!tmp) {
tmp = [NSMutableArray array];
[dictFromArray setObject:tmp forKey:eachKey];
}
[tmp addObject:eachDict];
}
//NSLog(#"dictFromArray %#",dictFromArray);
//NSLog(#"Unique Keys :: %#",aMutableArray);
//Converting from dictionary to array again...
self.finalArray = [[NSMutableArray alloc]init];
for (NSString *uniqueKey in aMutableArray) {
NSDictionary *aUniqueKeyDict = #{#"groupKey":uniqueKey,#"featureValues":[dictFromArray objectForKey:uniqueKey]};
[self.finalArray addObject:aUniqueKeyDict];
}
Hope, It will help when client wants final array in same order as input array.
NSMutableDictionary *expense_ArrContents = [[NSMutableDictionary alloc]init];
for (int i = 1; i<=4; i++) {
NSMutableArray *current_row = [NSMutableArray arrayWithObjects:#"payer_id",#"Expense_Type_id",#"Category_Id",#"SubCategory_Id",nil];
[expense_ArrContents setObject:current_row forKey: [NSNumber numberWithInt:i]];
}
NSArray *newArray = [expense_ArrContents allKeysForObject:#"payer_id"];
NSLog(#"%#",[newArray description]);
i want to get the list of key values containing the particular object which is in the array of values stored in nsmutabledictionary for a particular key.
In the line where you get all the keys ([expense_ArrContents allKeysForObject:#"payer_id"];) you actually get keys for an object that is not in any of the array's items. This #"player_id" is different object than the #"player_id" you added in current_row. In fact, maybe all of your rows have different #"player_id" objects (except if the compiler has made some optimization - maybe it threats that same string literal as one object instead of creating new object for each iteration).
Try creating an NSString object for the #"player_id" which you add to the current_row and then get all the keys for that same object:
NSString* playerId = #"player_id";
for(){
NSMutableArray *current_row = [NSMutableArray arrayWithObjects: playerId,...];
...
}
NSArray *newArray = [expense_ArrContents allKeysForObject:playerId];
Your NSArray *newArray = [expense_ArrContents allKeysForObject:#"payer_id"]; will not return any value because in expense_ArrContents there is no such key(#"payer_id"), instead there are keys like 1,2,3 etc.What is your requirement?Want to see what all keys are there in expense_ArrContents just log
NSArray*keys=[expense_ArrContents allKeys];
Try this :
NSMutableArray *array_key=[[NSMutableArray alloc]init];
for (NSString *key in expense_ArrContents) {
if ([[expense_ArrContents objectForKey:key] containsObject:#"payer_id"]) {
[array_key addObject:key];
}
}