iPhone: Fastest way to create a binary Plist with simple key/value strings - iphone

What's the best way to create a binary plist on the iPhone with simple string based key/value pairs? I need to create a plist with a list of recipe and ingredients. I then want to be able to read this into an NSDictionary so I can do something like
NSString *ingredients = [recipes objectForKey:#"apple pie"];
I'm reading in an XML data file through an HTTP request and want to parse all of the key value pairs into the plist. The XML might look something like:
<recipes>
<recipe>
<name>apple pie</name>
<ingredients>apples and pie</ingredients>
</recipe>
<recipe>
<name>cereal</name>
<ingredients>milk and some other ingredients</ingredients>
</recipe>
</recipes>
Ideally, I'll be able to write this to a plist at runtime, and then be able to read it and turn it into an NSDictionary later at runtime as well.

Creating a Property List in Objective-C
This contains information for creating a property list file using either CoreFoundation or Cocoa.

For your specific case, look at the interface for NSDictionary and use:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
+ (id)dictionaryWithContentsOfFile:(NSString *)path;
If you only need one fairly small dictionary, you could also try NSUserDefaults.
- (void)setObject:(id)value forKey:(NSString *)defaultName;
- (NSDictionary *)dictionaryForKey:(NSString *)defaultName;

Related

Loading text from a file

I am making an Iphone drinking card game app.
All the card mean something different and i want the user to be able to press an info button and then show a new screen with information about the current card. How can i make a document to load text from instead of using a bunch og long strings?
Thanks
You could look into plist files - they can be loaded quite easily into the various collection objects and edited with the plist editor in Xcode.
For instance, if you organize your data as a dictionary, the convenience constructor
+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
from NSDictionary would provide you with as many easily accessible strings as you need.
This method is useful if you consider your strings primarily data as opposed to UI elements.
Update:
As #Alex Nichol suggested, here is how you can do it in practice:
To create a plist file:
In your Xcode project, for instance in the Supporting Files group, select New File > Resource > Property List
You can save the file in en.lproj, to aid in localization
In the Property list editing pane, select Add Row (or just hit return)
Enter a key name (for instance user1) and a value (for instance "Joe")
To read the contents:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:#"Property List" withExtension:#"plist"];
NSLog(#"URL: %#", plistURL);
NSDictionary *strings = [NSDictionary dictionaryWithContentsOfURL:plistURL];
NSString *user1 = [strings objectForKey:#"user1"];
NSLog(#"User 1: %#", user1);
A plist, a JSON string, and an SQLite database walked into a bar ...
Oops!! I mean those are the three most obvious alternatives. The JSON string is probably the easiest to create and "transport", though it's most practical to load the entire thing into an NSDictionary and/or NSArray, vs read from the file as each string is accessed.
The SQLite DB is the most general, and most speed/storage efficient for a very large number (thousands) of strings, but it takes some effort to set it up.
In my other answer, I suggest the use of a dictionary if your texts are mostly to be considered as data. However, if your strings are UI elements (alert texts, window titles, etc.) you might want to look into strings files and NSBundle's support for them.
Strings files are ideally suited for localization, the format is explained here.
To read them into you app, use something like this:
NSString *text1 = NSLocalizedStringFromTable(#"TEXT1", #"myStringsFile", #"Comment");
If you call your file Localizable.strings, you can even use a simpler form:
NSString *str1 = NSLocalizedString(#"String1", #"Comment on String1");
A useful discussion here - a bit old, but still useful.

How to save data into an XML file

My application contains 8 TextFields. When I click the submit button I want to save all the values from the TextFields into an XML file (and generate a XML file if required). How can I do this?
Another XML writer which will get the job done is XSWI (shameless plug - I wrote that code).
There are many ways you could do this. One quick and dirty way of doing it is to generate a string in your code and insert the values
e.g.
NSString *myXML = [NSString stringWithFormat:#"<myxml><value1>%#</value1><value2>%#</value2></myxml>", textfield1, textfield2];
Then open a file and write myXML to it.
Not very elegant, but it depends on what exactly you want.
Do you need the XML file to be in a specific format? If not the easiest way is to save it as a plist (a type of xml file) by putting your strings into an array and then saving the array as a plist using
NSArray *array = [NSArray arrayWithObjects:label1.text, label2.text, label3.text, etc, nil];
[array writeToFile:fileName atomically:YES];
The nice thing about the plist is that you can easily load the string again by calling:
NSArray *array = [NSArray arrayWithContentsOfFile:filename];
If you need your XML in a different format from what the plist produces, the easiest way is probably just to build the XML yourself using string concatenation, e.g.
NSString *xml = [NSSString stringWithFormat:#"<root><label>%#</label><label>%#</label><label>%#</label>etc</root>", label1.text, label2.text, label3.text, etc];
You can use GDATAXML to read and write XML to file.
Refer this link to see how its done.
http://www.raywenderlich.com/725/how-to-read-and-write-xml-documents-with-gdataxml

Referencing file on disk from NSManagedObject

What would be the best way to name a file associated to a NSManagedObject. The NSManagedObject will hold the URL to this file.
But I need to create a unique filename for my file. Is there some kind of autoincrement id that I could use? Should I use mktemp (but it's not a temporary file) or try to convert the NSManagedObjectId to a filename? but I fear there will be special characters which might cause problem.
What would you suggest?
EDIT: I have a lot of these NSManagedObjects and each has its own image, so I want to generate a unique name for each picture.
You can use NSProcessInfo to generated the guid:
[[NSProcessInfo processInfo] globallyUniqueString]
And to reference a file I'd suggest just keeping the guid as NSManagedObject property and then just reference a file by that name from application support directory.
There is a good way to do this and one earlier answer almost had it – generate a GUID for each image instead of for the entire process. Call this method whenever you need a unique string, and then store it in the managed object:
+ (NSString *)getUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [(NSString *)string autorelease];
}
I use this for storing captured movies and images.
I thought about using the time to generate a unique filename but I don't like the solution, for instance if the time is reset or changed, there is a slight chance of getting two times the same filename.
I'm surprised not to find more information about this subject on the web.
Since iOS5 there is now the option to store large blobs in an external record file. CoreData decides whether or not to store the record in sqlite based on the size of the record.
Storing blobs in external location using built-in CoreData option

Sending array through email on iphone

Hey guys I need to send the content of an NSMutableArray through email. I have a mailing function but I'm not sure on how to place the content of the array into a NSString to be displayed on the email under each other. Is there a way to place all the content of the array into the string with maybe HTML nextline command between each array element?
NSString *emailBody = #"Need to put the body here";
Thanks
I'll suggest you convert your array into a text string using JSON. Then place the text in the email, send it away and use JSON on the receiving end to reconstruct the array.
You can get an iPhone version of JSON called TouchJSON here.
Claus
This process is known as serialization. Apple has a guide for it, that's worth reading through.
The simplest way is to call the array's description method which will return a human readable plist in a NSString.
If you need to reconstitute the array from the email. You will need save the array as xml plist using the writeToFile: method. Then read the file back in as a string. To reconstitute you will need to extract the xml from the email, put it in a NSString, write that to file, then read it back into an NSArray.
(IIRC, there used to be a way to write to NSString as if it was a file but I can't remember how to do it anymore. Probably, writing to a NSFileHandle and reading it back instantly.)
Edit:
Can you please explain more on the
array's description method please.
Like so:
NSArray *myArray=[NSArray arrayWithObjects:#"Obj1",#"Obj2",#"Obj3",nil];
NSLog(#"myArray=%#",[myArray description]);
...prints:
myArray=(
Obj1,
Obj2,
Obj3
)
For your project you can do:
NSString *arrayString=[myArray description];
The is also a descriptionWithLocale that will print the array in different languages. I don't have a ready example for that. See NSArray, NSLocale and The Locales Programming Guide

get element value

I have a NSString like that? (in iPhone application)
NSString *xmlStr = "<?xml version=1.0 encoding=UTF-8>
<information>
<name>John</name>
<id>435346534</id>
<phone>045635456</phone>
<address>New York</address>
</information>"
How I can get elements value?
(Do i need convert to XML format and get elements value? or split string? any way please tell me?)
Thank you guys.
If you want to use split string, you can use tokenization of strings using "componentsSeparatedByString" method. This is a more cumbersome method of course, rather than the recommended XMLParser
To get the name.
NSArray *xmlStr_first_array = [xmlStr componentsSeparatedByString: #"<name>"];
NSString *xmlStr_split = [NSString stringWithFormat:#"%#",[xmlStr_first_array objectAtIndex:1]];
NSArray *xmlStr_second_array = [xmlStr_split componentsSeparatedByString: #"</name>"];
NSString *name = [NSString stringWithFormat:#"%#",[xmlStr_second_array objectAtIndex:0]];
The most obvious solution is to use an XML parser to retrieve the values from each element.
You could use the excellent TBXML for this task. It provides a really simple interface where it wouldn't take more than a few lines to retrieve the desired values. The drawback to using this small library is that it (as far as I know) loads the entire XML data into memory. In this particular case, however, that is not problem at all.
There's of course also the option of using the NSXMLParser, though this is an event-driven parser, and thus a bit less simple to use.
Your string is in xml format already and you need to parse it to retrieve data. There're several options available - for example you can use NSXMLParser class or libxml library.
Edit: XMLPerformance sample project shows how to use both approaches and compare their performance.