I have to retain the score and current date for a game in a plist . I created a dictionary with two arrays:
- (void)viewDidLoad
{
[super viewDidLoad];
dateArray=[[NSMutableArray alloc]init];
scoreArray=[[NSMutableArray alloc]init];
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
[self getDate];
NSString *path = [[NSBundle mainBundle] pathForResource:#"score" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
int lastItemIndex = scoreArray.count;
[scoreArray insertObject:[dict objectForKey:#"scoreElements"] atIndex:lastItemIndex];
}
-(IBAction) saveData
{
NSString *plistPath =[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:#"Score.plist"];
NSMutableArray* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
[plistDict setValue:self.scoreLabel.text forKey:#"scoreElements"];
[plistDict writeToFile:plistPath atomically: YES];
}
This code is good only for the last game played, but I want to fill the tableView with the old scores as well. How can I do it?
Instead of using
[scoreArray insertObject:[dict objectForKey:#"scoreElements"] atIndex:lastItemIndex];
why don't you use
[scoreArray addObject: dict["scoreElements"];
Also when you are saving using below code, it will always set new value to "scoreElements" overriding old ones.... so you have to use array as well.
[plistDict setValue:self.scoreLabel.text forKey:#"scoreElements"];
You could use NSUserDefaults to store stuff and retrieve it later on.
Check out the reference about this class at Apple :
nsuserdefault apple
Related
I want to have access to the dealer name from the plist.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Cars" ofType:#"plist"];
NSArray *array = [NSArray arrayWithContentsOfFile:filePath];
NSMutableArray *dealers = [[NSMutableArray alloc] init];
for (NSDictionary *object in array) {
Dealer *dealer = [[Dealer alloc] initWithDictionary:object];
[dealers addObject:dealer];
}
self.dealers = dealers;
From this, i access just the first dictionary from plist
The first NSDictinonary in you plist has Item 0 key that store Dealer NSDictinonary. Change your string code
Dealer *dealer = [[Dealer alloc] initWithDictionary:object];
to this
Dealer *dealer = [[Dealer alloc] initWithDictionary:object[#"Dealer"]];
i recommend you check the variables-array,object
The usual method for loading data from a dictionary contained in a plist is as below:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
NSDictionary *data= [NSDictionary dictionaryWithContentsOfFile:path];
Is there a way to import only the element(s) specified in a key / set of keys, like:
NSDictionary *data= [NSDictionary dictionaryWithContentsOfFile:path forKey:key];
The idea is to perform lazy loading of dictionary contents by key.
So based on my comment above, you could add a class method to the NSDictionary via a category. You could do something like (not tested BTW).
+ (NSDictionary *)dictionaryWithContentsOfFile:(NSString *)path forKeys:(NSArray *)keys
{
NSMutableDictionary *newDictionary = nil;
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:path];
if (dictionary) {
newDictionary = [NSMutableDictionary dictionary];
for (id key in dictionary.allKeys) {
if ([keys containsObject:key]) {
newDictionary[key] = dictionary[key];
}
}
}
return [newDictionary copy];
}
If you did this, you'd see your spike in memory, but it should subside once dictionary is freed.
Alternatively, take a look at YAJL (https://github.com/lloyd/yajl). I've used this when dealing with very large JSON files. This was mainly the stream it in chunks. It is event driven, so you should be able to stream it in and detect the keys you want (hopefully).
please try the below method.
- (void)viewDidLoad
{
NSMutableArray *arry;
arry = [[NSMutableArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Catalog" ofType:#"plist"];
NSDictionary *dic = [menuArray objectAtIndex:indexPath.row];
lblName.text = [dic objectForKey:#"MenuName"];
}
I am trying to populate a UTTableView with the contents of my Data.plist file.
I need to load this into an NSMutableArray.
This is how far I came:
(View Did Load):
NSString *PlistPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
Array = [[NSMutableArray alloc] initWithContentsOfFile:PlistPath];
[Array addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:#"Testing 1", #"name", nil]];
And of course at CellForRowAtIndexPath:
cell.textLabel.text = [Array objectAtIndex:indexPath.row];
I wrote this in my Data.plist file (picture):
Now when I run the App. My TableView remains empty.
Thanks for your time and help!
Currently your plist's root is set to Dictionary. Change that to array first.
Then use this code to show the data:
cell.textLabel.text = [[Array objectAtIndex:indexPath.row] objectForKey:#"name"];
Why would the following implementation of the Dictionary cause a memory leak? See the screenshot below as well. Practically all of the leaks there are from this method.
- (void) setLocation:(NSString *) location:(NSString *) turnPage {
NSLog(#"Start setLocation");
//---get the path to the property list file---
NSString *localPlistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
NSMutableDictionary *copyOfDict;
//---if the property list file can be found---
if ([[NSFileManager defaultManager] fileExistsAtPath:localPlistFileNameConf]) {
//---load the content of the property list file into a NSDictionary object---
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:localPlistFileNameConf];
//---make a mutable copy of the dictionary object---
copyOfDict = [dict mutableCopy];
[dict release];
}
else {
//---load the property list from the Resources folder---
NSString *pListPath = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
//---make a mutable copy of the dictionary object---
copyOfDict = [dict mutableCopy];
[dict release];
}
location = [self checkLocationValidity:location:turnPage];
[copyOfDict setValue:location forKey:#"Location"];
[self writeConfigToFile:copyOfDict];
NSLog(#"End setLocation");
}
You're not releasing copyOfDict anywhere. You own any object created with a method that starts with copy, so you need to release those objects. It's probably misreporting the source as the original dictionary due to a bit of trickery in the NSDictionary class cluster for efficiency reasons. Try running analyse over your code, it should point these things out to you.
This is my code: (customNames and customNamesArray are static variables)
-(void) loadCustomDataFromDisk
{
NSString *fullPath = [self filePathAndFileName: #"customData.plist"];
if ( ![[NSFileManager defaultManager] fileExistsAtPath: fullPath] )
{
NSLog(#"Loading file fails: File not exist");
customNames = [[NSMutableDictionary alloc] init];
customNamesArray = [[NSMutableArray alloc] init];
}
else
{
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
customNames = [customItems objectForKey: #"customNamesDict"];
customNamesArray = [customItems objectForKey: #"customNamesArray"];
if (!customItems)
NSLog(#"Error loading file");
[customItems release];
}
}
-(void) saveCustomDataToDisk
{
NSString *path = [self filePathAndFileName: #"customData.plist"];
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] init];
[customItems setObject: customNames forKey: #"customNamesDict"];
[customItems setObject: customNamesArray forKey: #"customNamesArray"];
BOOL success;
success = [customItems writeToFile:path atomically:YES];
if (!success)
NSLog(#"Error writing file: customDataDict.plist");
[customItems release];
}
According to Build and Analyze, I have a potential leak in loading customItems
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
true enough, according to Instruments, I do have a leak in that part. But when I tried release or autoreleasing customItems, my app crashes. Even if I change NSMutableDictionary to NSDictionary, I still have the leak.
How do I fix this?
Any help would be very much appreciated. :) Thanks :)
You have to retain customNames and customNamesArray because you are using reference from dictionary customItems and after passing reference you are releasing it.
customNames = [[customItems objectForKey: #"customNamesDict"] retain];
customNamesArray = [[customItems objectForKey: #"customNamesArray"] retain];
Now you can release customItems.
Your code is right as I can see. You can see answer here and may be it helps - Leak problem with initWithContentsOfFile
I have only one question: You create NSString *fullPath and never release it. Is it autoreleased string? If so - your code is fine.