Refresh Value in NSMutableDictionary using ViewWillAppear - iphone

See this code:
int i = years;
NSLog(#"Years i: %i",i);
NSString *syears= [NSString stringWithFormat:#"%d",i];
menuList = [[NSMutableArray alloc] init];
[menuList addObject:[NSMutableDictionary
dictionaryWithObjectsAndKeys:
#"years", kLeftKey,
syears, kRightKey, nil, kControllerKey, nil]];
The above is an extract from ViewWillAppear. When I switch between tabs ViewWillAppear is doing it's job and the data is updating down as far as NSString *syears= [NSString stringWithFormat:#"%d",i]; but after that my array doesn't get updated with the latest value of syears. I tried using setObject and setValue but these don't work with NSMutableArray. Any ideas?

Keys and values in NSDictionary need to be non-nil NSObjects. So you've definitely got an issue with a nil in there, and there may be a question about kLeftKey et al, for which you haven't shown the definitions.
More generally, it would help to know what you are doing with menuList and what you mean by "my array doesn't get updated". Are you trying to display it? Using it as a data source somewhere? You are creating the array anew here -- could a previous reference be being left around and displayed?

Related

Only the last value of NSMutableDictionary is added to NSMutableArray

I have tried my best to search for the answers to add NSMutableDictionary to NSMutableArray. Unfortunately, they all asked me to use "[allValues]" which is not what I want.
Here is the issue,
In the header file, I defined,
NSMutableArray *arData;
And in the m file,
arData = [[NSMutableArray alloc] init];
NSMutableDictionary *mutableDictionary5 = [[NSMutableDictionary alloc]init];
for (i=0;i<[[[self rssParser]rssItems]count];i++)
{
Lat = [[[[[self rssParser]rssItems]objectAtIndex:i]lat] doubleValue];
Lng = [[[[[self rssParser]rssItems]objectAtIndex:i]lng] doubleValue];
// Creates a marker in the center of the map.
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(Lat, Lng);
marker.title = [[[[self rssParser]rssItems]objectAtIndex:i]header];
[mutableDictionary5 setObject:marker.title forKey:#"title"];
[arData setValue:[mutableDictionary5 valueForKey:#"title"] forKey:#"title"];
}
The "arData" only gets the last value of [[[[self rssParser]rssItems]objectAtIndex:i]header].And I am sure mutableDictionary5 gets all the value since I have put the following at the end of the code,
NSLog(#"mutableDictionary5 values=%#",[mutableDictionary5 allValues]);
It prints all the value of the title.
I understand it shouldn't be setvalue, however, I tried to use [mutableDictionary5 allValues], "addobjects", "allkeys". They are not working. What should I do to let the NSMutableArray arData to add all values of title with "title" as the key? thanks.
Sorry for my bad English which is not my native language.
You erroneously use setValue instead of addObject.
[arData addObject:mutableDictionary5];
This will work if you alloc init a new dictionary inside the loop.
If you want to reduce the array to just titles do this after the loop:
NSArray *titleArray = [arData valueForKeyPath:#"title"];
Now you have an array containing just titles.
BTW, you could make some effort to invent better variable names. Note that by convention in Objective-C variable names start with low cap while class names are capitalized.

NSDictionary won't write to plist

I'm trying to write an NSDictionary with a complex structure to a plist for use in an iPhone app. However, the file doesn't seem to write at all, and I have no idea why.
This is what the structure should look like:
Level Dict
Roads Array
Road1 Array
Vertex1 Dict
x Number
y Number
Vertex2 Dict
...
And this is what my code looks like:
NSMutableDictionary *levels = [[NSMutableDictionary alloc] init];
NSMutableArray *roads = [[NSMutableArray alloc] init];
for(ChainLinkRoad *r in data.roads){
NSMutableArray *road = [[NSMutableArray alloc] init];
for(ChainPoint *p in r.v){
NSNumber *x = [NSNumber numberWithFloat: p.x];
NSNumber *y = [NSNumber numberWithFloat: p.y];
NSMutableDictionary *vertex = [[NSMutableDictionary alloc] init];
[vertex setObject:x forKey:#"x"];
[vertex setObject:y forKey:#"y"];
[road addObject:vertex];
}
[roads addObject:road];
}
[levels setObject:roads forKey:#"Roads"];
bool b = [levels writeToFile:#"test.plist" atomically:YES];
//returns true
I've tried converting the mutables to their immutable counterparts, but that didn't work. I'm able to access data from the final NSDictionary (levels) just fine.
Edit: I should add that this plist is not for actual use in the iphone game. It's for personal use when designing levels. The code won't exist in the final version.
A common problem is, that the dictionary isnt valid for string transformation like invalid UTF-8 characters. Make a output on the console to check it.
If that doesnt help you, save only some elements to see what is going on.
I just posted an answer for this same issue yesterday. Instead of trying to save out the individual data elements of a class save the entire object using NSKeyArchiver and NSCoding. Click the link for a full explanation.
How can I save Array of Class Objects in to a Plist(Iphone Development)

Adding string to an array

i wanted to know how to add strings into an array.
I used the following methods but it is showing null.
1) [arrData addObject:[NSString stringWithString:strlast]];
2) [arrData addObject:strlast];
Thanks in advance
You can't add anything to an NSArray once it's created. You need to use an NSMutableArray if you want to make changes to it.
Update: You may actually have two problems.
Using an NSArray instead of an NSMutableArray when mutability is needed.
Not initializing the array object (either kind). If arrData is nil, you can happily send as many messages as you want to nil. Nothing will happen.
If it is showing null (nil) you need to make sure you set arrData somewhere in your code before trying to addObject:.
arrData = [[NSMutableArray alloc] init];
Also strlast is a string so use your second example, the first example is pointless.
[arrData addObject:strlast];
Did you allocate an array and assign it to arrData?
Try:
NSMutableArray *arrData = [NSMutableArray array];
NSString *string = #"My string";
[arrData addObject:string];
NSLog(#"%#", [arrData objectAtIndex:0]); //logs "My string"
If you're using a non-mutable array, you can also use arrayByAddingObject:
arrData = [arrData arrayByAddingObject: strlast];
but a mutable array is probably a better idea.

Objective C two-dimensional array memory issues

I'm trying to declare a two-dimensional array as an instance variable in Objective C. I've got the NSMutableArray in the header (data), along with the #property (nonatomic, retain). In viewDidLoad: I have:
data = [[NSMutableArray alloc] init];
[data addObject:[[NSArray alloc] initWithObjects:#"Cheese", #"Meat", #"Veggie", nil]];
[data addObject:[[NSArray alloc] initWithObjects:#"Sandwich", #"Soup", #"Stew", nil]];
I can NSLog the array within the method and it is correct, however when I try to Log it from a separate method I get nothing (just "#"), and if I try to access with
NSInteger num = [[data objectAtIndex:component] count];
it crashes with no error in the log. I'm sure this is something to do with not allocating memory properly, however I am new to Obj C and haven't worked with a C-style language in many years. FWIW, I have tried many variants of this that all fail, including using NSArray instead of mutable, [NSArray arrayWithObjects] instead of [[NSArray alloc] initWithObjects], and every combination in between.
try creating the outer array like this:
self.data = [NSMutableArray arrayWithCapacity:2]; // assuming you're only adding 2 inner arrays.
The following may be a right way.
self.data = [NSMutableArray array];
[data addObject:[NSArray arrayWithObjects:#"Cheese", #"Meat", #"Veggie", nil];
[data addObject:[NSArray arrayWithObjects:#"Sandwich", #"Soup", #"Stew", nil];
Note that, as #jamihash commented above, you need self.data to properly retain the array. And, there is no need to alloc the NSArray which you are adding to data.
As a side issue, you're retaining the child arrays twice. They get retained when you add them to your NSMutableArray, so you should probably autorelease them on creation or create them with one of the NSArray methods that returns an autoreleased array.
Your code by itself shouldn't crash. You should look into where and when you release and retain the NSMutableArray. You could post more of the code and I'm sure somebody will spot the problem.

iPhone SDK NSDictionary and NSArray confusion

I have been trying to get this to work for about three solid days and get my mind around it. Can someone advise.
I have built the basics and they all work great but when I try to do that extra bit I cannot get my head around it.
I am trying to build a table of technical terms, from a plist. This is an indexed and sections table by the alphabet.
This works fine but when I then try to add the next level for each term's definition in a new viewcontroller I can't seem to get the code or the plist structure right.
At the moment I have created two plists. One with a dictionary of the alphabet in 26 arrays, within each array is a series of technical terms. All this works great.
Then I've created another plist of definitions as an array of dictionaries, one for each word/definition pair. I'm expecting to be passing the #"word" key from the view controller to the detailviewcontroller then picking up the #"definition". I don't know whether this is right or wrong(?)
My code shows the technical term table great but when a row is selected it crashes. I know it's to do with the code for passing the detailviewcontroller's reference so the detailview can pick up the definition - but I've no idea how to solve it. I've posted parts of my code here for someone to look at help. Any ideas?
NSString *wordPath = [[NSBundle mainBundle] pathForResource:#"newsortedglossary" ofType:#"plist"];
NSDictionary *wordDict = [[NSDictionary alloc] initWithContentsOfFile:wordPath];
self.words = wordDict;
[words release];
NSArray *wordArray = [[words allKeys] sortedArrayUsingSelector:#selector(compare:)];
self.wordKeys = wordArray;
NSString *definitionPath = [[NSBundle mainBundle] pathForResource:#"newnewdefinitionglossary" ofType:#"plist"];
NSDictionary *definitionDict = [[NSDictionary alloc] initWithContentsOfFile:definitionPath];
self.definitions = definitionDict;
[definitions release];
didSelectRow here.........
GlossaryDetailViewController *glossaryDetailViewController = [[GlossaryDetailViewController alloc]
initWithNibName:#"GlossaryDetailView" bundle:nil];
NSLog(#"did select-2"); // CRASHES HERE with NSDictionary may not respond to objectAtIndex
glossaryDetailViewController.definition = [self.words objectAtIndex:indexPath.row];
NSLog(#"did select-3");
[self.navigationController pushViewController:glossaryDetailViewController animated:YES];
NSLog(#"did select-4");
[glossaryDetailViewController release];
detailViewController here.......
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"didappear");
self.glossaryWordDefinition.text = [definition objectForKey:#"definition"];
It seems that you are trying to access the members of dictionary by using an index, instead of using a key to lookup the associated value.
In your didSelectRow you probably want this:
glossaryDetailViewController.definition = [self.wordKeys objectAtIndex:indexPath.row];
The difference is that now you are trying access the members of an array with the index.