Create plist first in Xcode? - objective-c

I've read conflicting views on this
http://ipgames.wordpress.com/tutorials/writeread-data-to-plist-file/
If I want to use a plist to hold my tile map objects game data, do I have to create a plist with xcode first? and then update that? or do I not need to do that and I can just create it from scratch with code when the game runs?
If I don't have to create one with xcode first, what would be the benefit of doing that?

The code from your link is useful if you want some default data in the property list when the application is started for the first time.
If you don't need default data, don't have to create a property list in Xcode and include it in your application.
NSString *path = ... // path to plist file in Documents directory
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
if (plistDict == nil) {
// No plist present (or invalid contents), start with empty dictionary:
plistDict = [[NSMutableDictionary alloc] init];
}
Now you can add/modify/remove items in plistDict and save it later.

Related

Xcode - Write and Delete to Plist

I have a plist with two arrays that looks like this:
I currently load the plist like this:
// Find path of plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"nameofPList" ofType:#"plist"];
// Read the data into arrays
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSMutableArray *tableData = [dict objectForKey:#"array2"];
How do I write new items to the "array2" array in the plist (code, not manually)
How do I delete items from "array2"? (code, not manually)
Thank you.
You probably want:
NSMutableArray *tableData = [dict[#"array2"] mutableCopy];
^^^^^^^^^^^
(otherwise you'll get an immutable array).
Add items with:
[tableData addObject:#"new item"];
Delete with:
[tableData removeObjectAtIndex:someIndex];
or:
[tableData removeObject:someObject];
and anything else you can find in the NSMutableArray Class Reference.
However "write back" sounds like you are attempting to write the .plist back into the app bundle. While this will work in the iOS Simulator, it will fail on a real devices.
You cannot write to the app bundle at runtime; write to the Documents folder instead and be flexible about where to read from.

Objective c save to my plist

I have the plist file under the resources folder which is name is logical-app.plist
In ios8 if you want Gps will work then NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription keys should be added into the Info.plist
I want to add NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription keys in code in my appdelegate class.
Im trying to add the following code for solving this issue:
//write
filePath = #"/System/Library/CoreServices/SystemVersion.plist";
plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
[plistDict setValue:#"1.1.1" forKey:#"NSLocationWhenInUseUsageDescription"];
[plistDict writeToFile:filePath atomically: YES];
//endwrite
//read plist
filePath = #"/System/Library/CoreServices/SystemVersion.plist";
plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
value = [plistDict objectForKey:#"NSLocationWhenInUseUsageDescription"];
im trying to get
filePath = [[NSBundle mainBundle] pathForResource:#"ClickMobileCDV-Info" ofType:#"plist"];
and it is nil too....
But with no success.... when i read it from the plist it was nil...
How can i solve this issue?
You've completely got the wrong end of the stick. In order to add NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription, you edit the app's plist file within Xcode and it's included in the app bundle.
There is no code needed to read/write system .plist files at runtime (the writing of which would fail anyway, due to permission errors).

Xcode 4.6 localization within plist file

I have started adding more languages to a project of mine and got strings & graphics localized without much trouble.
I have one last problem and it is with a plist file.
This plist file holds default category names for the app and is filled with English strings in a dictionary.
My question is: is there a way to localize a plist file? I though about adding localized strings to the plist but could not figure out how.
I dont want to have to decide in code what plist file to take since the default plist file gets overwritten by the user upon first use.
Localized Plist files
Easier solution here would be to localize the entire plist. By doing so, you will have a different plist file for each supported language.
Select the plist file in your project, and select Localize in the File Inspector menu.
It will create a new folder containing a Plist file for each supported language.
From:
dummy.plist
To:
> en.lproj
> > dummy.plist
> es.lproj
> > dummy.plist
> de.lproj
> > dummy.plist
Localized Plist contents
Another solution would be to use localized strings inside the plist, and simply call NSLocalizedString before printing out the extracted string.
Imagine you had a Plist like this:
You can simply localize its strings by adding the keys to your Localizable.strings file. For example, in Spanish:
"My menu title" = "Mi título del menú";
"My menu description" = "Mi descripción del menú";
Or, my recommendation, move also your native language strings out of the Plist to a string file and replace the Plist strings with a localizable key:
And your Localizable.strings for Engligh:
"MY_MENU_TITLE" = "My menu title";
"MY_MENU_DESCRIPTION" = "My menu description";
and Spanish:
"MY_MENU_TITLE" = "Mi título del menú";
"MY_MENU_DESCRIPTION" = "Mi descripción del menú";
I've found the latest easier to maintain and easier to localize for new languages, as all the required strings are in the same file.
And finally change your code to use NSLocalizableString instead of the plain string read from the Plist file. For example, imagine you have the code:
NSDictionary* plistDict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"menuElements" ofType:#"plist"]];
menuTitleLabel.text = plistDict[#"menuTitle"];
menuDescriptionLabel.text = plistDict[#"menuDescription"];
Simply change it to:
NSDictionary* plistDict = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"menuElements" ofType:#"plist"]];
menuTitleLabel.text = NSLocalizedString(plistDict[#"menuTitle"], nil);
menuDescriptionLabel.text = NSLocalizedString(plistDict[#"menuDescription"], nil);
If this is your case you could get rid of the plist file completely:
menuTitleLabel.text = NSLocalizedString(#"MY_MENU_TITLE", nil);
menuDescriptionLabel.text = NSLocalizedString(#"MY_MENU_DESCRIPTION", nil);

Access the next item of a tableView populated by a plist

I have a tableView populated by a plist.
Each item in the plist has its own id.
The plist is structured like this:
Root
>Item 0
Title (Title of the first section in the tableView)
Rows (Array -> Rows of the first section)
>Item 0
id
name
description
image
>Item 1
id
name
description
image
//etc
Due that an image talks better than 1000 words, here it is:
Now, I would like to access to the next item of the plist from the detailView, but I don't know how to do or what the mechanism should be like.
I googled a lot to accomplish this but I didn't find anything that could actually help me, that's why I'm asking here.
I already have the plist opened in the detailView (opened from the tableView accessing the id), and I would like to create a button or something to go to the next item.
In example, if the detailView is the id of Item 0, I need to access the next id, which is Item 1 id.
Has anyone done this before?
Thank you very much in advance.
It's so easy, load your plist in DetailView and do the rest.
Start by importing the plist (this applies if it is stored in the bundle):
NSError *error = nil;
NSString *file = [[NSBundle mainBundle] pathForResource:#"Name" ofType:#"plist"];
if (!file) {
// Handle error if file not found
}
Then open the file as a dictionary (I am assuming you don´t need the initial array):
// Open the file
NSArray *array = [NSArray arrayWithContentsOfFile:file];
NSDictionary *dictionary = [array objectAtIndex:0]; // Skipped checking if array is empty
if (!dictionary) {
NSLog(#"Failed to process plist file"); // Handle error
}
Then you can query the dictionary for the object needed, i.e. an array with key #"MyKey" in this case:
NSArray *rowArray= [dictionary objectForKey:#"MyKey"];
Then you can retrieve next object from the array.

How to save apps data Xcode

I have been searching for many days on how to save my apps data. I found some stuff but it was very complicated and badly explained. I need that when I completely close my apps all the data I entered in the text field are still there when I open my apps again. I tried a tutorial but this only let me save about 8 textfields and I need to save thousands I am starting Objective-C and Xcode so if somebody want to give me an answer please make it very precise.
Alright, what I'd suggest would be putting all the data from your text fields into an array and saving that to a file, then loading it when you re-open the app.
The first thing you need is a save file. This function will create one for you.
-(NSString*) saveFilePath{
NSString* path = [NSString stringWithFormat:#"%#%#",
[[NSBundle mainBundle] resourcePath],
#"myfilename.plist"];
return path;}
Now that that's done you need to create your saving array. Hopefully you have your thousands of textfields already fitted into an array of some sort. If not, this will be a painful process regardless of how you tackle it. But anyway... (Here, labelArray will be the array of all your text fields/labels/etc.)
NSMutableArray* myArray = [[NSMutableArray alloc]init];
int i = 0;
while(i < labelArray.count){
[myArray addObject: [labelArray objectAtIndex: i].text];
i ++;
}
[myArray writeToFile:[self saveFilePath] atomically:YES];
[myArray release];
And the loading code would be something along the lines of
NSMutableArray* myArray = [[NSMutableArray arrayWithContentsOfFile:[self saveFilePath]]retain];
Then you'd simply load the data back into your array of text fields.
Hope this helps.
It sounds like your application architecture may be unsound if you are planning on saving thousands of text fields' data in the fraction of a second you get while your app is closing. It would probably be better to save these as the user enters the data instead of waiting to save all the data at once.
To get the path you are going to write ( or read from! ) to, you do the following:
NSString *writableDBPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"MyFile.extension"];
And then use a method like "writeToFile:automically:" of NSString or NSDictionary etc. to write to the path.