Saving, reading, exchanging own file format? - iphone

any recommendations for saving four strings into an own file format that is read by the application and can be shared?
In my app, you will be able to enter some text in some boxes and the app shows a view with an background image and those strings. Now, I am already able to save this as a picture, but I actually want to save it to an own file format so that you can save different files that can be modified afterwards as well or even exchanged via email and opened from another iphone with the app.
Now, I wrote the code for accessing the documents folder of the app, as well as saving and deleting. Thing is, i dont know how to store those strings in a file (perhaps in a xml?) and read them easily afterwards from my application.
For the exchanging part, I found that link which would be a nice feature indeed: http://iosdevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
Parsing xml seems not that difficult (never done it before): http://ipad.about.com/od/iPad-App-Dev/a/How-To-Parse-Xml-Files-In-Xcode-Objective-C.htm

If it's only a small bit of infomation then the easiest way to store your data in a file would be using a plist - there's a good tutorial here - http://www.icodeblog.com/2009/02/14/loading-data-from-plist-files/

In addition to the plist, you could also do the following approaches:
1) simplest - open a file in your documents directory, write the 4 strings (using whatever delimiter/end of string marker is useful - carriage return?) and overwrite them each time through. (i.e. it's your file, you can format it how you like)
2) mildly harder - use Apple's NSArchive to pack and unpack the strings.
3) possible overkill - store them directly in a SQLite database
4) major overkill - store them in CoreData.
Of course, the "overkill" options also provide you with extra features which may be of use if your app functionality extends beyond what you've outlined.
By sharing, I would think that simple copy and paste might be enough, but there's also sending it via email, or tripping another app's URL scheme to make it open it and sending the strings as part of the URL. You'd have to know that the other app would be able to interpret your strings as part of the URL, so you might have to write it yourself.

Okay guys I found that very nice method in the NSString documentation:
–writeToFile:atomically:encoding:error:
I think I am gonna separate my strings by /n and save them to a .txt. When I am gonna read the file afterwards, i am getting the string, divide it to substrings. That will do it, I guess.
One last question: Is it possible to replace the content of my file so that I won't need to create a new file every time i want to change something?
Thanks!

Related

coredata as front end and text files as backend

How does this sound conceptually.
I wanted to store some text and add tags to it thats easily retrivable. Coredata is the obvious solution, but i also needed that data across the cloud, not just iCloud like dropbox. So I thot i'd use Coredata + textFiles.
obvious approach
use coredata with two entities. One for text and one for tags. Works awesome BUT not ready for syncing.
1. using icloud coredata combo will hurt me badly, its still unreliable, and i cant afford to keep stabilising it.
2. i dont just have ios devices, need it on my computer too.
the solution
Add text in a simple textview.
Add tags to the text as well using some kinda delimiters.
Save the document as a text file (that includes tags) and give the document some unique name
Put that file in dropbox or icloud or whatever as a document But Also, parse it locally in the iOS app so that the text in file is separated into text and tags each of which enters its entity in coredata.
advantage for the solution
I can use the text in a useful way locally (in iphone) and if needed will get those text files from the cloud.
problem with the solution
Data in the cloud (as textfiles) is only so useful. But nonetheless, its there, i can live with this.
SYNCING: how do i make sure that each file is synced appropriately. Im not sure I should use UIManagedDocument? I'm already using coredata locally, dont know how i'd complicate things if i use UIManagedDocument.
My question is, im confused about the syncing and saving part, what should i do to keep it neat and clean.
While writing this question i feel like I screwed up the whole idea.

Prevent application cache from extracting files on iOS

I have an iOS application, which stores all downloaded *.pdf files in its cache. Is there a way to prevent this data from extracting? Encryption or something else? Thanks in advance.
There are quite a few ways to encrypt files, and I'm sure everyone will have an opinion on the best way to do so.
In a project I've recently been working on, we've been using CommonCrypto (https://github.com/AlanQuatermain/aqtoolkit). Just take any NSData, encrypt it, and save it to a file, and vice versa. You can even write an easy Transformer by subclassing NSValueTransformer, which abstracts all of the encryption to one spot and you will never have to worry about it again.
You can protect PDF files with a password. I assume you create the PDF files not within the application but externally. For example you can use Preview.app in Mac OS X to secure existing PDF files with a password (Hit Cmd-P, then select PDF in the print menu and there you can set security options. Or even more simple: in the menu choose Export...).
In iOS you can then open the PDF files like this:
CGPDFDocumentRef documentRef = CGPDFDocumentCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:filePath]);
if (!CGPDFDocumentIsUnlocked(documentRef))
CGPDFDocumentUnlockWithPassword(documentRef, password);
...
There are actually 2 Documents folders in which your app can store content. One can be extracted, and one is private. Check the accepted answer in this ticket.
Access files in "private Documents" folder transferred with iTunes
Assuming you want the PDF files from getting extracted on jailbroken devices, the most straight forward approach would be along the following lines:
generate a random string during the first launch of the app
save the random string either in NSUserDefaults in state file inside your own app's sandbox
using this random string create a secret key using a deterministic but hard to figure out algorithm
use this secret key, which you don't store anywhere but always generate on demand, symmetrically encrypt your buffer with AES or something similar
You would probably find the source code here very helpful.

Valid file types for iCloud?

I find many similar question but i didn't get solution for this.
Is it possible to upload some file like image, document, zip file to upload on iCloud programmatically?
See table 4-1 in the documentation:
How do you manage the data? Manage files and directores using the
NSFileManager class. Open, close, read, and write files using standard
file system routines.
So if you can create a file, you can store it in iCloud. But remember there's a finite, relatively small amount of space available.
iCloud can handle all kinds of files. So if you want rot use an obscure file format or invent your own, go for it. It only can to be converted into a byte stream/NSData, but then again, what isn't?
Check this tutorial walkthrough app. It shows how to create, modify and delete files for iCloud.
http://github.com/lichtschlag/iCloudPlayground

How to deliver a multilingual FAQ within an app?

I want to ship my app with a built-in FAQ on the settings page. The FAQ is simple:
1) We have a table view which lists all the questions. One per cell.
2) When the user taps one of those questions, we slide over to a detail view controller which shows the question in bold letters and then the answer. Very simple.
The hard part: What would be the optimal way to feed the table view and detail view controller with the strings?
Bad ideas (from my point of view):
Hardcode all strings and work with giant if or switch monsters.
Rely on NSLocalizedString() to fetch the localized version of an answer. Those strings files don't look like they were intended for very large strings. Just for a few sentences or words per line. With tons of FAQ text those strings files would become horrifying.
This is how I'd attempt to do it, but you may suggest a better way:
Solution 1)
Create an JSON file where entities have three fields: ID, Question and Answer. ID will help us track down which Answer we have to load after the user tapped a cell.
Localize that JSON file.
When the table view loads, read it into memory and parse it, just to read out the questions and ID's (yes, less than ideal, right?)
When the user taps a cell, either pass the ID just to re-fetch the whole thing again, or maybe better: Pass the ID, question and answer strings to the details view controller.
Solution 2)
Like 1, but use Core Data instead. Probably better for memory and performance, but probably harder to maintain (must mess around with a SQLite3 file to build the FAQ, needs at least a good IDE to do that to not go crazy). Caveat: Can't pass it to translators easily. Tons of manual work just to create that SQLite3 file. Files localized in localization folders.
Solution 4)
Two splitted JSON files: One with all the ID's and Questions. Another with all the ID's and Answers. Files localized in localization folders.
Solution 5)
An JSON file with all the IDs and Questions. For every ID, there's a matching Answer text file. So we don't end up loading tons of data into memory just to extract some tiny fraction of it.
Solution 6)
Use something that already exists, or a different approach. Suggestions?
Normally, you would localize a localizedStrings-file, so that they can get translated when you run NSLocalizedString. What you may not know is that this basically works for all kinds of files, so plists too:
Create a localized faq plist-file.
Request it (from in the app) with [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"faq" ofType:#"plist"]];
Implement it in your UITableView. (- (NSInteger)numberOf... => return [faq count];).
Oh, and I use a plist-file instead of JSON or XML since Apple uses it, since it's really easy to implement (NSArray - arrayWithContentsOfFile is built in) and you can maintain it very easily in Xcode.

How often should I save to the file?

I'm developing a simple text editor for iPad.
Instead of Core Data, the app just saves its content to *.txt file in the document folder by calling writeToFile function of NSString. In this way, users can easily transfer files via iTunes. Please, advise me if this approach is bad or inefficient!
How often should the program save its content to the text file? The iOS human guide says that the app should save it's content "frequently" but it doesen't give specific seconds.
I read somewhere that the app should save its content every two seconds. If this is correct, do I just need to make one function and call it using NSTimer with repetition mode?
Thank you!
There's little point in saving "frequently" unless you actually expect to crash. iOS gives you notification of potential app shutdown situations, so I'd just save upon: 1) Receiving a memory warning 2) Termination 3) Moving to background and 4) Whenever the user asks for it (be that via a button, or by navigating away from the editing view). Any saving beyond that is really a waste of resources, as the actual editor isn't going anywhere, short of crashing out.
The writeToFile method of NSString is fine for plaintext and assuming you've got your data as an NSString already. If your data isn't already inside an NSString, then there are more efficient ways of saving it than converting to an NSString and calling writeToFile (output streams, for example). Also, if you're using very large files, you'll probably want a more incremental approach (i.e. saving from just the point of change to the end). The odds of anyone editing a file large enough on the iPad to need this though, are slim.