Data is not adding to Plist - ios

Hi i created one plist in xcode (newfile->resourses->property list like this) and i try to add one NSDictionary to that plist but its not adding ,please help me here is my code
-(IBAction)Add:(id)sender {
_pdfbookmark = [NSMutableArray arrayWithArray:[[NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pdfBookmarksdata" ofType:#"plist"]] objectForKey:_bookID]];
NSMutableDictionary *bookmark = [NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"pdfBookmarksdata" ofType:#"plist"]];
if(self.bookmarkIndicator.tintColor == [UIColor blueColor]){
//Already Bookmarked
[_pdfbookmark removeObjectAtIndex:currentBookmarkIndex];
self.bookmarkIndicator.tintColor = [UIColor whiteColor];
}else{
//Create Bookmark
[_pdfbookmark addObject:
#{#"deviceid": #"0",
#"page" : [NSNumber numberWithInt:[self getGlobalPageCount]],
#"fontsize" : [NSNumber numberWithInt:currentTextSize]}];
self.bookmarkIndicator.tintColor = [UIColor blueColor];
}
[bookmark setObject:_pdfbookmark forKey:_bookID];
[bookmark writeToFile:[[NSBundle mainBundle] pathForResource:#"pdfBookmarksdata" ofType:#"plist"] atomically:YES];
}

You are not allowed to write files to your main bundle. If you check the return of the writeToFile: method, you will see that it returns NO.

Related

Dictionary from plist

i have 3 plist files with named level0, level1, level2, all of this plist have the same structure, it consist of number variable and array. I init my app with data from this plist.
+(instancetype)levelWithNum:(int)levelNum; {
NSString* fileName = [NSString stringWithFormat:#"level%i.plist", levelNum];
NSString* levelPath = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:fileName];
NSDictionary *levelDic = [NSDictionary dictionaryWithContentsOfFile:levelPath];
NSAssert(levelDic, #"level no loaded");
Level *l = [[Level alloc]init];
l.coinsPerLvl = [levelDic[#"coinsPerLvl"] integerValue];
l.words = levelDic[#"words"];
return l;
}
Now i decide to use only one plist and add in it 3 dictionary. How can i read only one dictionary from plist like in example above where i use plist files.
Tanks for any help!
you only need an intermediate variable thats represents the root dictionary and extract the level dictionary from the root dictionary, e.g:
+(instancetype)levelWithNum:(int)levelNum; {
NSString *levelsPlist = [[NSBundle mainBundle] pathForResource:#"levels" ofType:#"plist"];
NSDictionary *rootDict = [NSDictionary dictionaryWithContentsOfFile: levelsPlist];
NSString *levelKey = [NSString stringWithFormat:#"level%i", levelNum];
NSDictionary *levelDic = rootDict[levelKey];
NSAssert(levelDic, #"level no loaded");
Level *l = [[Level alloc]init];
l.coinsPerLvl = [levelDic[#"coinsPerLvl"] integerValue];
l.words = levelDic[#"words"];
return l;
}
Hope it help.
make your plist root as an array (like below). that way you can get levels info easily.
sample code
+(void)levelWithNum:(int)levelNum {
NSString* fileName = #"level.plist";
NSString* levelPath = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:fileName];
NSArray *levelsArray = [NSArray arrayWithContentsOfFile:levelPath];
NSAssert(levelsArray, #"level no loaded");
Level *l = [[Level alloc]init];
l.coinsPerLvl = [[levelsArray objectAtIndex:levelNum][#"coinsPerLvl"] integerValue];
l.words = [[levelsArray objectAtIndex:levelNum][#"words"] integerValue];
return l;
}
sample plist screen shot

How do I get values from a tiered .plist?

I've already looked at Parse Plist (NSString) into NSDictionary and deemed it to be not a duplicate, as that question and its answer do not address my concerns.
I have a .plist file in the file system structured like this:
The source code of this .plist file looks like this:
{
"My App" = {
"Side Panel" = {
Items = {
Price = "#123ABC";
};
};
};
}
I know how to get an item in the Root like this:
[[NSBundle mainBundle] pathForResource:#"filename" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSString value = [dict objectForKey:#"key"]);
But what if the structure is like mine, with tiered dictionaries? How do I get the value of Price?
I would like to do this all in one method, ideally like this:
Calling
NSString *hexString = [self getColorForKey:#"My App.Side Panel.Items.Price"];
Definition
- (NSString *) getColorForKey: (NSString *)key
{
NSArray *path = [key componentsSeparatedByString:#"."];
NSDictionary *colors = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Colors" ofType:#"plist"]];
NSString *color = #"#FFFFFF"; // white is our backup
// What do I put here to get the color?
return color;
}
Here's the solution that worked for me:
+ (NSString*) getHexColorForKey:(NSString*)key
{
NSArray *path = [key componentsSeparatedByString:#"."];
NSDictionary *colors = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Colors" ofType:#"plist"]];
NSString *color = #"#FFFFFF";
for (NSString *location in path) {
NSObject *subdict = colors[location];
if ([subdict isKindOfClass:[NSString class]])
{
color = (NSString*)subdict;
break;
}
else if ([subdict isKindOfClass:[NSDictionary class]])
{
colors = (NSDictionary*)subdict; // if it's a dictinoary, our color may be inside it
}
else
{
[SilverLog level:SilverLogLevelError message:#"Unexpected type of dictinoary entry: %#", [subdict class]];
return color;
}
}
return color;
}
where key is an NSString that matches /^[^.]+(\.[^.]+)*$/, meaning it looks like my targeted #"My App.Side Panel.Items.Price".
Yes I understand what you're looking to accomplish; thank you for the clarification. I will however add that the resources and advice I have written do provide the necessary information resolve your problem.
That said, the following gets your dictionary:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:#"Info" withExtension:#"plist"];
NSData *plistData = [NSData dataWithContentsOfURL:plistURL];
NSDictionary *tieredPlistData = [NSPropertyListSerialization propertyListWithData:plistData
options:kCFPropertyListImmutable
format:NULL
error:nil];
Then, if we're interested in the information contained in Items
NSDictionary *allItemsDictionary = tieredPlistData[#"My App"][#"Side Panel"][#"Items"];
Assuming that Items will contain a number of objects, you could use
NSArray *keys = [allItems allKeys];
for(NSString *key in keys){
NSString *colorValue = allItemsDictionary[key];
// do something with said color value and key
}
Or, if there is a single value you need, then just reference that key
NSString *colorForPriceText = allItemsDictionary[#"Price"];
But a few tips:
It's generally considered a better idea to keep frequently accessed values in code instead of a plist/file that is loaded at runtime.
That said, you wouldn't put your call to load from NSBundle in the same method you would use to query a specific value. In your example, every time you need a color, you end up re-accessing NSBundle and pile on unneeded memory allocations. One method would load the plist into an iVar NSDictionary and then that NSDictionary would be used separately by another method.

Adding score and current date to plist

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

how to load plist data into array in IOS property list

NSString *path = [[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"]];
NSDictionary *dict = [[NSDictionary alloc] initwithContentOfFile:path];
NSArray *textData=[NSArray new];
textData = [dict objectForkey:#"TableData"];
textData is my array name,
recipes is plist name
after excuting my text data is being empty...
where is the mistake.
The problem is that you converting .plist to dictionary in the wrong way. Check dict property, it should be nil. Code to create NSDictionary from .plist file is listed below:
CFPropertyListRef plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
(__bridge CFDataRef)propertyListData,
kCFPropertyListImmutable, NULL);
NSDictionary *settings = (__bridge NSDictionary *)plist;
Try this:
textData = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"]];
Anyways, you may can take a look of this tutorial:
http://ios-blog.co.uk/tutorials/how-to-populate-a-uitableview-from-a-plist-property-list/

Plist to NSDictionary

I have some plist data like the one on the below image:
How do I access the "Text" value, if an NSDate equal to CDate is selected on my UIDatePicker?
So you basically want
NSString* path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
NSArray* a = [NSArray arrayWithContentsOfFile:path];
for (NSDictionary *d in a)
{
NSString *cdate = [d objectForKey:#"CDate"];
if ([cdate isEqualToString:#"Whatever is currently selected"])
{
NSString *text = [d objectForKey:#"Text"];
// do something with text here
}
}
Stumbled across this and thought an update was due
NSDictionary *initialDefaults = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"Defaults" ofType:#"plist"]];

Resources