ObjC: Write to .plist, optimized way? - objective-c

Reading this article for instance, writing an NSDictionary to a plist looks pretty easy. Now, if I just want to modify one single row of an existing plist: Is there any way to update the row without re-writing the whole file?
Like "when updating a row in a database table, I don't have to rewrite the whole table"?
Thanks,
J.

First : plist is for very trivial data, so there should not be the question of optimisation of reading and writing it. As if you need to optimise that, that means you need to change your application design.
Second : plist is basically an xml file, so of course you can use xml parsers.

Theoretically, you could do modifications faster under the condition that the lengths of the string representation of your new value takes up precisely as many characters as that of the old value. However, this would be a bad case of micro-optimization: unlike a database where rewriting an entire table may take considerable time, rewriting a plist in its entirety should go unnoticed, as far as the timing is concerned. Your code to locate and overwrite the old value in a file would not be pretty by any standard. It has no chance of matching the clarity of a three-line "read-modify-write" code fragment that rewrites the whole thing.
This assumes that you are using your property list for its intended purpose, which is storing relatively small amounts of data. If you are using a plist to store moderate to large amounts of data, perhaps you need to switch to using a database, where updating individual rows is permitted.

Where is the sense in that?
Despite what has already been said, that plist, who use XML, is designed for small amounts of data and that it could work properly only when the new value does not make any change to the length (string representation within the XML) of your value, there is hardly any bargain to make.
Frankly I do not know what the cluster (or however the smallest fraction of allocable disk space is named in iOS' file system) size is but I would not expect it to be much smaller then the average size of a typcal plist file. In all file systems that I know a cluster will allways be written in one go. Even if the programmer just changes a byte and tries to write only that one byte back to the file, the OS will allways write the full cluster on disk (or whatever there is that we still call a disk :).
Meaning - even if you try hard, you will hardly gain anything from that attempt.
Unless of course, your data structure is rather big and probably complex for a plist file. In that case, as it has been said already, consider a change to the data storage method that you are using.

From an other answer:
You have:
a plist file
a container (for example, NSMutableArray) in which you load this plist
a table view which takes values from this container.
To modify plist through table view:
change value in container
write container back to plist file.

Related

Saving Data - Core Data vs plist file

I'm writing an iOS applications that saves Music albums(just an exercise I'm doing for the fun of it) .
For every Album there's a singer, song names, time, and a picture
The final result will be a lot of objects with a lot of details including a picture attached to every object. Should I even consider doing something like that with plist? (can pictures be stored in a plist?)
What's the best way to save and access that data?
I'm new to iOS and from the training videos I've seen Core Data is not recommend for the beginner user. Is that really the case?
If I'm going with plist, should I create one plist for every genre for example rap.plist , rock.plist etc' or just a big data.plist?
Thanks
I would go for core data. If you choose the right template when you create your new project in xcode then reduce the once-off overhead work significantly.
With that simple structure I would say that the templates provides nearly everything you need. Just define your model and layout and off you go.
There is just the images where I would spend a bit more time in thinking it over. I personally never put the image data into core data itself. I rather stored them as file and within my core data model I just stored the path and filename to access it. As file name I simply used a timestamp. You could use some auto-increment or other unique id technique but a time stamp would do as well. It will not be visible to the user anyway.
I think the best way you can do this, since you are new to IOS is by using sqlite. Save all the information you want in your local database and display it on the screen.
You can use plist if you have data structure that is small.
Note that property lists should be used for data that consists primarily
of strings and numbers. They are very inefficient when used with large blocks
of binary data. A property list is probably the easiest to maintain, but it will be loaded into memory all at once. This could eat up a lot of the device's memory.
With Sqlite you will easily be able delete , edit, insert your data into the database.
Core data also uses sqlite for data storage only it helps you to manage your data objects, their relationships and dependencies with minimal code.
And since your are new getting started with core data would not be such a good idea i think.. so i would suggest start off with normal sqlite. Save the data in one of your folders of your app and store their path in the database.
You dont have to write different plists.. You can use the same one if you are using.
EDIT : here is a link that will help you with learning sqlite
http://www.iosdevelopment.be/sqlite-tutorial/
you need some more code to set up the core data stack (the store coordinator, the store, the object model, and a context)
it is a tad more complicated but that shouldnt scare you off.
Reading a plist is indeed dead easy but while good for smaller data (like the info.plist) it doesnt scale and soon you need a fullblown DB
As you edited your original question an decided to go with plist now.
In that case I would go for one plist per ablum and one overall plist for the list of albums.
You could, of course, use more plists for categories etc.
However, if you are thinking of data structures like categories you are far better off with core data. Especially when it comes to searching.
No one seems to be mentioning SQLLite, I would go that way and for reasons that I explain here ( https://stackoverflow.com/a/12619813/1104563 ). Hope this helps!
coredata is a apple provided persistant tool, while plist is XML file. The reason why core data is not recommended for beginner, I think, is core data is more difficult than plist from programming perspective. For your application, obviously core data is more suitable. But alternatively, you may also use archive file, that's between core data and plist.

What are the downsides of plain text files as configuration files with only a few values in iOS?

Why use plists and xml files? If I only want to store a few values, is it okay to use plain text files or does this go against Objective-C best practices?
-------EDIT-------
I'm not sure if this should go in a separate post or not, so I'll just put it here...
If I'm making an app where a user can design a cupcake and save it with their preferences (color, flavor, size), which method should I use. I imagine my users aren't going to make hundreds of designs, but some will inevitably make a large number.
I'd say it's fine, but considering how easy they make it to read plist files, my question would be why bother?
The main reason that plists are commonly used is because the native APIs can handle these easily. You can load a NSArray/NSDictionary directly from a plist with one command.
SQL databases are used when you are going to have many occurrences of similar data. For example, if you need to record contacts for a social app, you would use a database that could contain the id, name, age, gender, phone number, email, etc.
Other than these, there are custom binary formats, but these are specialized for whatever project is being worked on. Depending on what you need to accomplish, a text file could work for you, but there may be better answers. There is nothing wrong with using text files, but these are not commonly used as you would have to write your own methods to parse them. Really, I would need to know more about what type of data you will be storing before I could tell you which option would be best.
An edit to answer your edit:
For this, the best thing to do would be to use a SQL database, as every cupcake is going to have various properties, such as name, type of cake mix used, type of frosting, color of frosting, sprinkles yes/no, etc. This is perfect for a SQL database, because dbs have named colums (ie "name", "mixType", etc), and each row in the table will have different values for each of these columns.
This could also be implemented with a plist, but it wouldn't be as efficient, and it would use more disk space (although not much if youre just using it for cupcakes). I assume that you have a Cupcake class, so you could just implement a load function like this:
+(id)cupcakeWithContentsOfFile:(NSString*)file {
if((self = [super init])) {
NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile:file];
self.flavor = [plist objectForKey:#"flavor"];
// Etc.
}
return self;
}
This is an interesting question. I actually have an app out there that DOES indeed use simple text files for data that the app uses. Because the original code came from a windows / mac program, and I wanted to keep the data files consistent, Windows doesnt provide pfile type operation. I wrote all of the code on windows to read in the files, and since it was all ANSI-C it transported to MacOS X quite nicely.
When it came to porting it over to the iPhone and iPad, it still was just as easy to port the code then to re-write not only the data files into PList format, but also the PList reading code.
For All apps that I have begun from scratch that arent windows bound also, I have used PLists though.
This is actually an issue that I go back and forth on. PList and / or XML reading and processing is certainly NOT going to be as high of performance as a well designed text file format as both are bloated due to all of the excess tags that may or may not be necessary. If you are trying to develope a single data file that has many types of data, than this could be the simpler approach, but if you are looking for less datasize, and maybe faster execution, then formatting your own file may be much better. I know this isnt a definitive answer.
So in the end, it isnt a "best practices" sort of thing, but really a preference type of thing.

Search plist for integer

In an iOS app, I take a four digit code from the user and give them a corresponding string in a TextView. My question is, because there are about a thousand possible codes the user would enter that I am checking for, what is an efficient way to give a result without having a huge if or switch statement? Like, using a plist, txt file, or even database.... Thanks in advance
The decision of plist, text file or database is just a matter of storage, not search. Personally, I would just use a JSON file, since it's reasonably well-supported both by the human brain and by software. For searching, just put them in an NSDictionary and do a lookup on that. Unless your items are very big, 1000 items is not really a large dataset, even on a memory-constrained iPhone. Even if each item is 1 KB (which sounds a lot larger than the dataset you're describing), you're looking at less than a megabyte for the whole set.
If the strings happen to be long, then store the long text in a file and store the file URL in your lookup table instead of the whole string. IIRC, a URL is about 100 bytes on average, and an NSNumber is about 8, so you'd be looking at about 108 KB for the entire dataset.
Given the number of possible codes I would recommend Core Data. Alternatively you can use SQLite directly. You could use a plist, but I fear it would quickly become unmanageable as you add, remove, and update codes.

What object to hold a large amount of text in?

I am planning a Seaside app to hold text, a single instance which may be up to, say, 5Mb. What kind of object is best for this?
I would also like to do some iterations over this text.
Thanks, Vince
Edit: Thanks for your replies thus far. The file is a CSV file that takes ~40 minutes to generate from a legacy finance system, so it must be pre-generated and stored. Each line is a customer record and I need to pull each one out and use the values as and when the customer logs in. Customer access is not predictable and interfacing with the legacy system to generate each line on the fly is a very last resort.
Given that the file takes that long to generate and that you need more-or-less random access to the file later on, I would opt for parsing the file and keeping the structured data in memory afterwards.
There is a CSV Parser project on Squeaksource that you can use. It will create a structured object tree of the CSV records that you can use.
Use an external Text file and some instance of a specific class as representation of that file. Use the oop of the object as the name of the file.
Just use a collection of customers, and fill it from the CSV, as Johan said. Depending on your accessing needs you can use a Dictionary or an OrderedCollection to hold it.
5 megs is nothing. Don't worry about that.
If you can't reify those CSV records into objects (after parsing and instantiating them), then a Collection of Strings or even Streams would be just fine.
If you need keyed lookup then a Dictionary or LookupTable would do the job.
I had 100 megs of text data in memory (1 millon rows), and even persisted in the image (image save) with no problems.
Regards.

Store and loading large plists

I am parsing some xml and storing the result in a plist save it to file. I later frequently use that plist to search, add/remove stuff and then save it back.
Now, I don't have any problem with this, everything works fine, im just wondering if there's a better/more efficient/faster way of doing this?
About the plist: array of 200 dictionaries with 150 entries each. Some of those entries are array themselves with sub dictionaries of 50-100 entries... (you get the point)
Thanks.
Unless you are running into performance problems I would suggest not worrying about it and just focus on getting the rest of app completed. Premature optimization is the root of all evil (someone had to say it right?).
If you decide that the time has come to make that part of your app as efficient as possible then we would need to see that actual code that you are using to determine if there are more efficient ways to do it. Considering your description of the plist I would guess that if there was anything incredibly inefficient with your strategy and/or implementation then you would already be running up against it with respect to performance.