I am writing an app that copies a plist into the docsdir and then reads it into a mutable array. The code below, however, returns a count of 0 for the array. The line with the dictionary log, however, returns the correct items. I have also verified that the file is being copied to the docsdir.
-(NSString *)docsDir {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *listPath = [[self docsDir]stringByAppendingPathComponent:#"list.plist"];
if (![[NSFileManager defaultManager]fileExistsAtPath:listPath]) {
[[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:#"list" ofType:#"plist"] toPath:listPath error:nil];
NSLog(#"Chicken");
}
NSLog(#"%#", [NSDictionary dictionaryWithContentsOfFile:listPath]);
_array = [NSArray arrayWithContentsOfFile:listPath];
NSLog(#"Count: %i", [_array count]);
}
- (void)viewDidUnload
{
[super viewDidUnload];
/ / Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Usually this is because by default root element in plist files is a Dictionary.
Right click and select Open as Source Code, your file may look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>foo</key>
<array>
<string>foo1</string>
<string>foo2</string>
<string>foo3</string>
</array>
</dict>
</plist>
where the root element is a dict, change it to:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>foo1</string>
<string>foo2</string>
<string>foo3</string>
</array>
</plist>
where the root element is an array. You can now edit as usual.
Open the plist file with Xcode.
Just find the 'key' at the top left corner and Type of the plist.
Make sure the Type is Array.
I think your plist is a dictionary that contains an array.
Try this
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:listPath]
NSArray *array = [dict objectForKey:#"key"];
Plists are usually saved a dictionaries:
Here's an example :
<dict>
<key>tiltingAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.25</real>
<key>animationFrames</key>
<string>1,2,3,4,5,5,4,3,2,1,2,3,4,5</string>
</dict>
<key>takingAHitAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.1</real>
<key>animationFrames</key>
<string>5,5,7,8,8</string>
</dict>
<key>blowingUpAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.2</real>
<key>animationFrames</key>
<string>5,6,7,8,9,10,11,12,13,14,15,16,17</string>
</dict>
<key>transmittingAnim</key>
<dict>
<key>filenamePrefix</key>
<string>radar_</string>
<key>delay</key>
<real>0.3</real>
<key>animationFrames</key>
<string>5,6,5,6,5,6,5</string>
</dict>
</dict>
Now, there are 2 solutions to your question.
Either get the contents into a dictionary then take out the array for a specific key.
Open up the plist with a text editor and change the root key into then change root into . If your plist is static and in the bundle resources then you could do this but if it's a plist generated by your code then i wouldn't recommend this.
Related
I have a plist that looks like the following.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!--
Translations
-->
<plist version="1.0">
<array>
<dict>
<key>English</key> <string>Hello Mrs./Mr./Miss.</string>
<key>French</key> <string>Bonjour Madame / Monsieur / Mademoiselle.</string>
<key>Spoken</key> <string>Boh(n)-zhoor mah-dahme/ muh-syuhr/ mah-dah-mwa-sell.</string>
</dict>
<dict>
<key>English</key> <string>Excuse me.</string>
<key>French</key> <string>Pardon.</string>
<key>Spoken</key> <string>Par-doh(n).</string>
</dict>
<dict>
<key>English</key> <string>Do you speak English?</string>
<key>French</key> <string>Parlez-vous anglais?</string>
<key>Spoken</key> <string>Par - lay vooz ah(n)-glay?</string>
</dict>
</array>
</plist>
I want to know how to find how many elements are in the plist. For example, there is 3 in the code above. Is there an attribute of plist I can call to find this number?
Read the plist into an array:
NSArray *plistArray = [NSArray arrayWithContentsOfFile:pathToPlistFile];
and count the number of elements:
NSUInteger count = [plistArray count];
I am writing a tweak for jailbroken iOS devices and I want to be able to write this NSString "bundleID" and the integer created in my code to a plist file. The code below can do this, however, it only does this once and doesn't allow me to write it to the plist multiple times. I want to do this because the bundleID changes and should also be written to the plist. Basically what I want to do is when an app is launch the bundle id for that app (com.apple.mobilesafari) is written as the key in my plist. I then have code to work add 1 to the value every time the app is opened. So for example if I opened mobile safari four times the plist should look like this.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.mobilesafari</key>
<integer>4</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
</plist>
However, when I launch mobile safari four times it stays as...
<key>com.apple.mobilesafari</key> <integer>1</integer>
I also want the bundleID saved for every app. So if I open safari then contacts I want both in my plist. For example...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.mobilesafari</key>
<integer>1</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
<dict>
<key>com.apple.contacts</key>
<integer>1</integer>
<key>customText</key>
<false/>
<key>enabled</key>
<false/>
</dict>
</plist>
Here is my objective-c code...
%hook SBApplicationIcon
-(void)launch
{
// Return original method
%orig;
// Get Bundle ID
NSString* bundleID = [self leafIdentifier];
// Print that badboy!
NSLog(#"Bundle ID: %# ",bundleID);
// Set up plist
NSMutableDictionary *launches = [[NSMutableDictionary alloc] initWithContentsOfFile:#"/var/mobile/Library/Preferences/com.bengerard.ipslider.plist"];
// Check plist exists
NSString *pathToFile = #"/var/mobile/Library/Preferences/com.bengerard.apppop.plist";
BOOL isFile = [[NSFileManager defaultManager] fileExistsAtPath:pathToFile isDirectory:NO];
if(isFile)
{
// Counting
int count = [[launches objectForKey:bundleID] intValue];
count++;
// Write number of launches to plist
[launches setObject:[NSNumber numberWithInt:count] forKey:bundleID];
//[launches insertObject:[NSNumber numberWithInt:count] forKey:bundleID];
[launches writeToFile:#"/var/mobile/Library/Preferences/com.bengerard.apppop.plist" atomically:YES];
}
else {
//The file doesn't exit.
}
// [bundleID release];
// [pathToFile release];
// [launches release];
}
%end
P.S: I am also using theos by DHowett to compile my tweak.
Edit: Realised my two plists are different. Probably causing my problem. I will test later
I'm a new developer for the iPhone. I have a plist file (named "Favorites") in main bundle.
I need to write the data with the following structure, for 20 dictionary items.
how would I write?
<array>
<dict>
<key>PubDate</key>
<date>2011-08-12T23:15:12Z</date>
<key>ImageName</key>
<string>abc.png</string>
<key>Title</key>
<string>ABCDEF</string>
<key>Description</key>
<string>Suggestions?</string>
</dict>
<dict>
<key>PubDate</key>
<date>2011-08-12T23:15:12Z</date>
<key>ImageName</key>
<string>abc.png</string>
<key>Title</key>
<string>ABCDEF</string>
<key>Description</key>
<string>Suggestions?</string>
</dict>
<dict>
<key>PubDate</key>
<date>2011-08-12T23:15:12Z</date>
<key>ImageName</key>
<string>abc.png</string>
<key>Title</key>
<string>ABCDEF</string>
<key>Description</key>
<string>Suggestions?</string>
</dict>
Well don't expect people to write out all the code for you, but this is probably close to what you're looking for.
//Put this where you want to write the data. add is the filename you want to save under
[info writeToFile:[self saveFilePath:add] atomically:YES];
//Put this somewhere in your class
- (NSString*) saveFilePath: (NSString *) add
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:add];
return filename;
}
I will Suggest you to make a Java type dictionary bcoz a dictionary is immutable so you create it once and you can't add or remove objects. For a Java like dictionary you need to use NSMutableDictionary....
I am trying to create an NSMutableDictionary containing a list of animals in my iOS app with this function.
// puts animals into dictionary
- (void) putAnimalsFromPlistToDictionary
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:#"myAnimals" ofType:#"plist"];
myAnimalDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
// I set a breakpoint here in XCode.
}
I dragged myAnimals.plist (which looks like the below) into my supporting files folder for my application.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>elephant</string>
<string>monkey</string>
<string>cat</string>
</array>
</plist>
However, when I reach the breakpoint (as listed in my comment), I see that myAnimalDictionary is nil. Why?
Perhaps it's because you have an array in your .plist but you're trying to instantiate a mutable dictionary instance.
First, a little background. I am trying to make a platform game. In front of the game layer I want "lights" to go by and by lights I mean white triangles. I am trying to get coordinates for the triangles from a plist.
At this point I have spent days trying to get my app to read from a plist and I cannot get it to work.
This is what I currently have and this is basically what the internet is saying I should have and that it should work.
In helloWorld.h:
NSMutableArray *foregroundLights;
In helloWorld.m
NSString *path = [[NSBundle mainBundle] pathForResource:#"foregroundlights" ofType:#"plist"];
foregroundLights = [[NSMutableArray alloc] initWithContentsOfFile:path];
I have tried formatting the patch every way that I can think of, I have tried using NSSearchPathsForDirectoriesInDomains. I have tried making the plist a dictionary and making it an array. What am I missing?
Here is a piece of the plist. The full one contains 50 arrays of 4 ints.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>root</key>
<array>
<array>
<integer>128</integer>
<integer>68</integer>
<integer>246</integer>
<integer>7</integer>
</array>
<array>
<integer>181</integer>
<integer>84</integer>
<integer>170</integer>
<integer>62</integer>
</array>
<array>
<integer>118</integer>
<integer>51</integer>
<integer>142</integer>
<integer>64</integer>
</array>
</array>
</dict>
</plist>