Plist to NSDictionary - ios

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"]];

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 to know index of current Object with name

I have an array called poemcollection
poemcollection = [[NSMutableArray alloc] initWithObjects:
[[NSBundle mainBundle] pathForResource:#"twinkle_twinkle" ofType:#"mp3"],
[[NSBundle mainBundle] pathForResource:#"baa_baa_black_sheep" ofType:#"mp3"],
[[NSBundle mainBundle] pathForResource:#"johny_johny" ofType:#"mp3"],
on button click
I want to know which object is playing currently from this array and index of this object.
I want to print in log this both name and index of current file playing on player
[poemcollection indexOfObject:YOUR_CURRENT_PLAYING_OBJECT];
Something like this?
-(void)printCurrentlyPlaying
{
NSString *mediaFileName = [[self.player.url absoluteString] lastPathComponent];
BOOL found = NO;
int poemIndex = -1;
for(int i = 0; i < poemcollection.count && !found; i++)
{
NSString *filePath = poemcollection[i];
NSString *fileName = [filePath lastPathComponent];
if([fileName isEqualToString:mediaFileName])
{
found = YES;
poemIndex = i;
}
}
if(found)
{
NSLog(#"Currently playing: %#, track number: %d", mediaFileName, poemIndex);
}
}
You can keep a mapping dictionary for the media name, e.g -
poemCollection = #[ #{"Twinkle twinkle": [[NSMutableArray alloc] initWithObjects:
[[NSBundle mainBundle] pathForResource:#"twinkle_twinkle" ofType:#"mp3"]},
#{#"Baa baa black sheep": [[NSBundle mainBundle] pathForResource:#"baa_baa_black_sheep" ofType:#"mp3"]},
#{"Johny Johny": [[NSBundle mainBundle] pathForResource:#"johny_johny" ofType:#"mp3"]}];
//And read the title like below :
NSString *title = [poemCollection[index] allKeys][0]
NSString *musicFile = [poemCollection[index] allValues][0]
try this code to get current file name and object.
NSString *currentFile = [[self.player.url absoluteString] lastPathComponent];
[poemcollection indexOfObject:currentFile];

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.

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/

How could I have .plist path inside iPad / iPhone

How could I have a complete list of each .plist path (inside iPhone/iPad) ?
In iOS Simulator I'm using it : ls -l ~/Library/Preferences/com.apple.*.plist
My goal is to find a specific key and read the boolean value in preferences.
Because I need to know if it is enable or not.
It is something that is missing in SDK but is existing in preferences.
NSLog (#"%#", [[NSBundle mainBundle] pathsForResourcesOfType:#"plist" inDirectory:#"/"]);
The method returns an NSArray.
You need to create the plist first. All you have to do is access it when you need it.
NSArray *thePlist;
NSString *plist = [[NSBundle mainBundle] pathForResource: #"plistFileName" ofType: #"plist"];
thePlist = [[NSArray alloc] initWithContentsOfFile: plist];
Thank you Daniel A. White , Jahm and Kedar!
I code this to summarize each comment :
With an extra, add an example to read UISupportedInterfaceOrientations values.
NSLog(#"Preferences plists from apple (inside iPhone/iPad) are not accessible from code");
NSLog (#"Accessible plist paths : %#", [[NSBundle mainBundle] pathsForResourcesOfType:#"plist" inDirectory:#"/"]);
NSArray *pList = [[NSBundle mainBundle] pathsForResourcesOfType:#"plist" inDirectory:#"/"];
for (int i = 0; i < [pList count]; i ++)
{
NSString *plistPath = [pList objectAtIndex:i];
NSDictionary *plistDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSMutableArray *nameString = [plistDictionary objectForKey:#"UISupportedInterfaceOrientations"];
for (NSString *n in nameString)
{
NSLog(#"Supported Interface : %#",n);
}
}

Resources