How to clear a NSTableView's data source - objective-c

I am trying to make a method in which the data source for my NATableView is cleared, but I cannot figure out how to do this anywhere.
Here is the code I am using to send an array called final to my table view.
// I want to clear it here before filling it again.
for (int i = 0; i < [final count]; i++) {
[myArrayController addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:final[i], #"File Name", nil]];
}
Any help would be great!

If you are using an NSMutableArray and myArrayController is your mutable array you want to call
[myArrayController removeAllObjects];
before you enter the for-loop.

Related

Interpreting a data stream in objective c

I am getting a stream from a live feed. It looks something like this as a mutableArray:
"Columbia Heights",
E04,
"Cleveland Park",
A05
The first line is a name and the second is a station code.
I need to turn this into a dictionary that is Plist compliant.
So the result in mind would look like this:
name:
"Columbia Heights",
code:
E04,
name:
"Cleveland Park",
code:
A05
What I've written so far is this:
NSMutableDictionary *stationDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"Name",#"name",#"Code",#"code", nil];
int i = 0;
for (i=0; i < counter; i++) {
// get names and codes for each of 3 fave stations
//[stationArray addObject:[mutableFaveArray objectAtIndex:i]];
NSString *tempName = [mutableFaveArray[i] valueForKey:#"name"];
NSString *tempCode = [mutableFaveArray[i] valueForKey:#"code"];
[stationDict setObject:tempName forKey:#"name"];
[stationDict setObject:tempCode forKey:#"code"];
}
I'm no longer getting an error, but I get as output, the same as my input.. I'm also only getting the last record..
"Cleveland Park",
A05
Updated Code:
NSMutableDictionary *stationDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"Name",#"name",#"Code",#"code", nil];
int i = 0;
for (i=0; i < mutableFaveArray.count; i++) {
NSString *tempName = [mutableFaveArray[i] valueForKey:#"name"];
NSString *tempCode = [mutableFaveArray[i] valueForKey:#"code"];
[stationDict setObject:tempName forKey:#"name"];
[stationDict setObject:tempCode forKey:#"code"];
[stationArray addObject:stationDict];
}
This results in the last dictionary entry being saved twice..
{
code = A05;
name = "Cleveland Park";
},
{
code = A05;
name = "Cleveland Park";
}
The problem is that you're only creating a single dictionary, stationDict, before the for loop. You then hit the for loop, which changes the values in stationDict, adds stationDict to the stationArray, changes the values in stationDict again, adds that same dictionary to stationArray, and so on. What you end up with is an array that contains the same object repeated mutableFaveArray.count times.
The solution is to either create a new dictionary at the beginning of the body of the for loop, or add a copy of the dictionary to add to the array. So, either this:
for (i=0; i < mutableFaveArray.count; i++) {
stationDict = [NSMutableDictionary dictionary];
//...continue with the rest of your code...
or this:
//...other for loop code precedes this...
[stationArray addObject:[stationDict copy]];
}
Either approach ensures that each thing you add to the array is a dictionary that's distinct from the others you've added. As a refinement, you could probably speed up the code a little by using a non-mutable dictionary. If you have to create a new dictionary each time through the loop, you can create it with the data you want it to contain rather than changing the objects, so you don't necessarily need it to be mutable. Also, you can declare the loop variable inside the for statement, which ensures that it'll go out of scope as soon as the for terminates. Also, you can use Objective-C's notation for dictionaries:
NSMutableArray *stationArray = [NSMutableArray array];
for (int i=0; i < mutableFaveArray.count; i++) {
[stationArray addObject:#{#"name":mutableFaveArray[i][#"name"],
#"code":mutableFaveArray[i][#"code"]}];
}
You can further abbreviate that and maybe speed it up a bit using fast enumeration:
NSMutableArray *stationArray = [NSMutableArray array];
for (NSDictionary *fave in mutableFaveArray) {
[stationArray addObject:#{#"name":fave[#"name"],
#"code":fave[#"code"]}];
}
Or you can let mutableFaveArray do the enumerating for you:
__block NSMutableArray *stationArray = [NSMutableArray array];
[mutableFaveArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop))
{
[stationArray addObject:#{#"name":obj[#"name"],
#"code":obj[#"code"]}];
}];
That last one might be a bit faster, but perhaps a bit harder to read.

How do I append an object to NSMutableArray?

I want to update an mutable array. i have one array "ListArray" with some keys like "desc", "title" on other side (with click of button.) i have one array name newListArray which is coming from web service and has different data but has same keys like "desc" "title". so i want to add that data in "ListArray" . not want to replace data just add data on same keys. so that i can show that in tableview.
..........So my question is how to add data in "ListArray". or any other way to show that data in tableview but replacing old one just want to update the data
NSMutableArray *newListArray = (NSMutableArray*)[[WebServices sharedInstance] getVideoList:[PlacesDetails sharedInstance].userId tokenValue:[PlacesDetails sharedInstance].tokenID mediaIdMin:[PlacesDetails sharedInstance].minId mediaIdMax:[PlacesDetails sharedInstance].maxId viewPubPri:#"Public_click"];
NSDictionary *getNewListDic = [[NSDictionary alloc] initWithObjectsAndKeys:newListArray,#"videoList", nil];
[listVidArray addObject:getNewListDic];
NSArray *keys = [NSArray arrayWithObjects:#"desc",#"url",#"media_id",#"img",#"status",#"media_id_max",#"fb_url",#"title", nil] ;
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for(int i = 0 ; i < [listVidArray count] ; i++)
{
for( id theKey in keys)
{
// NSMutableArray *item = [NSMutableArray array];
NSLog(#"%#",theKey);
NSLog(#"%#",keys);
[dict setObject:[[[listVidArray objectAtIndex:i]valueForKey:#"videoList"] valueForKey:theKey] forKey:theKey];
// [dict setObject:[newListArray valueForKey:theKey] forKey:theKey];
}
}
If you the newListArray is totally different from the oldListArray, then clear the old one, and use the new data to fit it.
Otherwise, you need to merge the two arrays. One way is to check if a
data in newListArray is/is not in oldListArray and then decide
whether to add it into oldListArray.
When oldListArray is updated, call -reloadData of the tableView.
If I do not misunderstand your question, you may do something like this:
[listArray addObjectsFromArray:newListArray];
[_tableView reloadData];

objective-c changing array contents inside for loop

I have an issue that (I think) might have to do with scope, but I'm not sure. I'm trying to do something that I think should be simple, but I am getting a strange result, and I could truly use some advice. I would say I'm an early-objective-c programmer, but not a complete newb.
I have written a function in objective-c that I would like to use to change the key-names in a mutable array of mutable dictionary objects. So, I want to pass in a mutable array of mutable dictionary objects, and return the same mutable array with the same dictionary objects, but with some of the key-names changed. Make sense?
I have tried several log statements in this code, which seem to indicate that everything I'm doing is working, except when the for loop is finished executing (when I try to test the values in the temp array), the array appears to contain only the LAST element in the source array, repeated [source count] times. Normally, this would lead me to believe I'm not writing the new values correctly, or not reading them correctly, or even that my NSLog statements aren't showing me what I think they are. But might this be because of scope? Does the array not retain its changes outside of the for loop?
I have put a fair amount of time into this function, and I have exhausted my bag of tricks. Can anyone help out?
-(NSMutableArray *)renameKeysIn:(NSMutableArray*)source {
/*
// Pre:
// The source array is an array of dictionary items.
// This method renames some of the keys in the dictionary elements, to make sorting easier later.
// - "source" is input, method returns a mutable array
*/
// copy of the source array
NSMutableArray *temp = [source mutableCopy];
// a temporary dictionary object:
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
// These arrays are the old field names and the new names
NSMutableArray *originalField = [NSMutableArray arrayWithObjects:#"text", #"created_at",nil];
NSMutableArray *replacedField = [NSMutableArray arrayWithObjects:#"title", #"pubDate", nil];
// loop through the whole array
for (int x =0; x<[temp count]; x++) {
// set the temp dictionary to current element
[dict setDictionary:[temp objectAtIndex:x]];
// loop through the number of keys (fields) we want to replace (created_at, text)... defined in the "originalField" array
for (int i=0; i<[originalField count]; i++)
{
// look through the NSDictionary item (fields in the key list)
// if a key name in the dictionary matches one of the ones to be replaced, then replace it with the new one
if ([dict objectForKey:[originalField objectAtIndex:i]] != nil) {
// add a new key/val pair: the new key *name*, and the old key *value*
[dict setObject:[dict objectForKey:[originalField objectAtIndex:i]]
forKey:[replacedField objectAtIndex:i]];
// remove the old key/value pair
[dict removeObjectForKey:[originalField objectAtIndex:i]];
}// end if dictionary item not null
}// end loop through keys (created_at, text)
[temp replaceObjectAtIndex:x withObject:dict];
}// end loop through array
// check array contents
for (int a=0; a<[temp count]; a++){
NSLog(#"Temp contents: ############ %#",[[temp objectAtIndex:a] objectForKey:#"pubDate"]);
}
return temp;
} // end METHOD
I think the issue is on the line with:
[dict setDictionary:[temp objectAtIndex:x]];
Since these things are almost all working in pointers (instead of copying contents), every element of your temp array will point to the dict dictionary, which is set to be whatever the latest key's dictionary is. I think setting the actual pointer will fix the issue.
dict = [temp objectAtIndex:x];

object inside NSMutableArray is not update immediately after updating

I have a very strange error using NSMutableArray in cocos2d/xcode
In my code, I have a NSMutableArray containing object A
NSMutableArray *peasantArray;
and another NSMutableArray contain object B
NSMutableArray *treeArray;
in the scheduled update function, I called another function which is essentially the following functionality:
I would loop through all the object A inside the *peasantArray, and if any peasant object has a variable var == GameEntityCommandIdling, I would modify the object B in the second NSMutableArray *treeArray,
The issue is that I notice sometimes after I modified the object A inside the peasantArray, the modified variable (var) is being modified/updated inside the object A after by printing out the variable status in a scheduled fashion; but if I am to loop through the NSMutableArray *peasantArray again in the next schedule (1/30s), I will again find the object A with the older/un-updated variable (var), and this is causing my algorithm to be wrong,
However, if I loop through the NSMutableArray *peasantArray less than 1second, each time I would see the variable (var) for object A correctly as the updated variable value,
So is there a limit on how fast I can iterate over the NSMutableArray?
here are some piece of code that I basically just mentioned,
NSMutableArray *peasantArray;
NSMutableArray *treeArray;
.....
peasantArray = [[[NSMutableArray alloc] initWithCapacity:1]retain];
for(int i = 0; i < 1; i++)
{
Peasant *A = [[Peasant alloc] init];
[peasantArray addObject:A];
}
....
//inside the update()
for (int i = 0;i < [peasantArray count];i++)
{
Peasant *A = [peasantArray objectAtIndex:i];
if (A.status == something)
{
printf("A.status is something\n");
A.status = sometingelse;
...
//update other things not related to this NSMutableArray or object
}
}
.....
SO the error is that sometimes I will have multiple printf of "A.status is something", although only one of it should be printed,
I really appreciate any help,
Thanks,
So is there a limit on how fast I can iterate over the NSMutableArray?
Definitely no. That would be the stupidest implementation of an array I'd ever encountered. :)
The simplest explanation is usually the answer. You say the message is printed more than once. Well have you checked that maybe more than one Peasant has its status set to something?
If that's not the case, are you certain the status update is printed twice in the same frame, and not twice in two subsequent updates?
Earlier on you seemed to indicate that the effect of iterating over one array and modifying the other array's objects is invalidated somehow. That made me want to point out that if you have the same object in both arrays, modifying the object's properties in array A will also modify the properties of the same object contained in array B.
You may want to give breakpoints a(nother) try. The problem should be easy to locate when you step through the code.
Here you have a memory leak
for(int i = 0; i < 1; i++)
{
Peasant *A = [[Peasant alloc] init];
[peasantArray addObject:A];
}
you should release A after adding it to the array since the addObject adds a reference count to the object.
for(int i = 0; i < 1; i++)
{
Peasant *A = [[Peasant alloc] init];
[peasantArray addObject:A];
[A release];
}

NSMutableDictionary, alloc, init and reiniting

In the following code:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict initWithDictionary:[anArray objectAtIndex:i]];
}
Why this crash? How is the right way to clear an nsmutabledict and the assign a new dict?
Thanks guy's.
Marcos.
You do not "reinit" objects — ever. Initialization is meant to be used on a newly alloced instance and might make assumptions that aren't true after initialization is complete. In the case of NSMutableDictionary, you can use setDictionary: to completely replace the contents of the dictionary with a new dictionary or addEntriesFromDictionary: to add the entries from another dictionary (without getting rid of the current entries unless there are conflicts).
More generally, you could just release that dictionary and make a mutableCopy of the dictionary in the array.
If you use an autoreleased dictionary, your code will be a lot simpler:
NSMutableDictionary *anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
for (int i=1; i<5; i++)
{
anMutableDict = [NSMutableDictionary dictionaryWithDictionary:[anArray objectAtIndex:i]];
}
But I don't see the point of that loop you have at the end there.
This isn't how you use init/alloc. Instead, try:
//anArray is a Array of Dictionary with 5 objs.
//here we init with the first
NSMutableDictionary *anMutableDict = [[NSMutableDictionary alloc] initWithDictionary:[anArray objectAtIndex:0]];
... use of anMutableDict ...
//then want to clear the MutableDict and assign the other dicts that was in the array of dicts
for (int i=1;i<5;i++) {
[anMutableDict removeAllObjects];
[anMutableDict addEntriesFromDictionary:[anArray objectAtIndex:i]];
}