Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

SERAPHRowen

macrumors newbie
Original poster
Sep 15, 2010
11
0
Hey all, first post, but I've been lurking for a few weeks. I'm a C++ coder, and I've been tasked with learning the Mac world. So far so good. I've read Cocoa programming for Mac OSX and written a few sample apps, and I think I'm ready to dig in. EXCEPT, I'd like some advice before I dive in.

My first program will be similar to an address book. I need to store an object with simple data such as, strings, gregorian dates, etc... and do file io on it. My first instinct was to create my own class, and create an NSMutable array, and when it came time to do file io, convert my entire array into one gigantic string with magic character separators, and deconstruct/reconstruct my object, and save out and load the entire string at once into a single file. That worked, but I was worried about the magic character seperator (heaven forbid someone use a magic character in one of their strings).

I'm now second guessing that approach entirely. I've run into a few classes that seem to be very useful for what I'm doing. NSDictionary seems ideal, however, it seems like if I wanted to use that, each object would need it's own file... so I could potentially have 300 saved out NSDictionaries each with the same keys... it seems wrong for obvious reasons. I next thought about doing something similar to above, but use an array of NSDictionaries and then do the same construction deconstruction into and out of a string as I was doing before, but there must be a better way.

I'm researching now into NSCoder and NSCoding, and it seems promising. This approach would be using my own custom class, and just handling my own fileio.

So my question to you is... how would YOU handle the data in a program like this? Is there some native data type I'm unaware of that will contain a number of objects(or dictionaries) and do file io brilliantly? Or is doing it myself with NSCoder the best approach? Any help would be very much appreciated.

-Than
 

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,425
A sea of green
There isn't a single universal answer. It depends on how much data you expect to have, and what kind of search or index operations you intend to perform.

Dejo already suggested Core Data. I can't disagree, because I have no idea what scale your data is.

As for 300 NSDictionary's stored as plist files, I don't see that as a major problem, as long as you're systematic about storing the files. And I have no idea what "the obvious reasons" are for why you think this is wrong. And again, without knowing what you expect to do with the data, and the expected size, this is all just guesswork.

In short, it's impossible to make a specific suggestion because you haven't defined any of the limits, constraints, or requirements of the program or its data.


BTW, any "magic character" can be escaped, taking away its magic. For example URLs use the % character to introduce an escaped byte. NSLog() and printf() also have a "magic character", which is coincidentally also '%', and a literal '%' thus has an escaped form (%%). C and Objective-C source have an escape character in quoted strings: backslass; it's used for control characters like tab, newline, etc. and for including literal quotes (backslash-quote) in the string. HTML uses ampersand to escape characters, including <>.

An escape character is a pretty common thing, and doesn't have to be the ASCII ESC character:
http://en.wikipedia.org/wiki/Escape_character
 

adrian.oconnor

macrumors 6502
Jan 16, 2008
326
3
Nottingham, England
NSCoder is very good, so is core data, so are databases in general. However, if you're learning to code and want to be a better programmer, you should try and implement each solution that you can think of (try and do it in a modular way so you can switch the export code with minimal effort) because that kind of experience is invaluable. You should definitely start with the plain text approach (I use § and ± as magic characters whenever this kind of problem crops up). Also try saving it out as quoted-CSV.

As a full-time programmer, every now and again I need to deal with exactly these sorts of problems, and the fact I've actually done this in the past means I have a really good idea of what the solution will look like before I even begin. Just two weeks ago in fact somebody sent me a corrupt Excel CSV file that I had to deconstruct.

If you're actually just looking for a quick solution and don't care about any of that, ignore me :)
 

adrian.oconnor

macrumors 6502
Jan 16, 2008
326
3
Nottingham, England
Actually, I just re-read your post and it seems you don't need the how-to-suck-eggs advice in my previous post, because you probably know all of that.

Here's my answer(s), given you know what you're doing:

NSCoder is awesome. You can code/decode the object graph so easily. It works for all kinds of classes, so you can use it for saving/restoring your GUI too (just code/decode your viewcontroller classes etc). I'd definitely recommend giving it a go.

CoreData is a nice persistence framework. I've used it in simple-but-real-world cases (I used it to persist a collection comprising just one class) but it should scale out quite well and you don't have to think about the database at all.

OS X includes Sqlite, even on iPhone. If you've used it before you can just re-use your existing knowledge. It's good.

± and § make good magic characters on Mac. NSString includes plenty of methods for handling strings, and you can use standard IO to load/save your data. I used those characters recently to delimit data that I was transporting between JS on a web page and a Cocoa touch app that was hosting it. I used more than one character in the sequence. Obviously if someone enters the exact same sequence and you don't encode it your app breaks.
 

SERAPHRowen

macrumors newbie
Original poster
Sep 15, 2010
11
0
First of all, thank you for the responses. You guys are awesome.

My scope of data is relatively small, I'm assuming the maximum will be around 300 objects, each with a couple of strings, an int or two, and perhaps a gregorian date or two.

The "obvious reasons" I mentioned perhaps are not so obvious unless you are in my head. My primary concern is these will all need to be loaded on app init, and potentially saved on app exit. I'm not sure how fast or slow that is on iOS devices, but in the programming environment I'm used to, I'd do my best to avoid having to load or save 300 files at once.

I've never used SQL, though I may dig into it just to explore possibilities. From what I understand, my two best options are Core Data and NSCoder. I'll dig into those two, research some more, and if I feel inspired post the results. Thanks again for the help guys.

Also, the tidbit about magic characters was very useful. Thank you.
 

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,425
A sea of green
First of all, thank you for the responses. You guys are awesome.

My scope of data is relatively small, I'm assuming the maximum will be around 300 objects, each with a couple of strings, an int or two, and perhaps a gregorian date or two.

That's a pretty small data set. A single plist file would likely suffice. If there's an indexable structure, it might be splittable into multiple plist files.

The "obvious reasons" I mentioned perhaps are not so obvious unless you are in my head.
No IP address, no URL, so no one else can access it.

My primary concern is these will all need to be loaded on app init, and potentially saved on app exit. I'm not sure how fast or slow that is on iOS devices, but in the programming environment I'm used to, I'd do my best to avoid having to load or save 300 files at once.
Now we know the concern. Unfortunately, you haven't stated why this is a concern. Do you have to load all the data at once because it's unindexed? Solution: index it and store the index. Some other reason? Explain.

In almost every situation I can think of, I'd avoid loading 300 files. This suggests doing some non-repeating work to avoid loading 300 files, such as indexing the data, or storing the data in an implicitly indexed form. Example of the latter: files stored with filenames that are keywords, with hard-links or symlinks for multiple keys that refer to the same target object(s). This is just an ad hoc index, exploiting file-system behavior for a different purpose. Would it work in this case? Only you can tell.

You wouldn't have to save the data on app exit, if you've written the data to disk during a lull in user activity, or shortly after any changes are made.

In any case, you should make a test program to exercise the data store and measure performance, where the actual storage mechanism is encapsulated under a uniform API. Then you can change the data storage mechanism without affecting any other parts of the program.
 

adrian.oconnor

macrumors 6502
Jan 16, 2008
326
3
Nottingham, England
You know, thinking about it, I'd say CoreData is your best fit. It abstracts the database away, which is a good thing if you're not a database person, and saves you the hassle of managing hundreds of files. I wish I remembered what resources I used to build my first core data app. I'll look them up in my delicious bookmarks later and post them (I'm on my iPad right now). It was probably just the docs on the Apple dev site. I remember it being quite easy.
 

SERAPHRowen

macrumors newbie
Original poster
Sep 15, 2010
11
0
So, I did end up using Core Data.

Some of the resources I've used so far and are using:
http://developer.apple.com/library/...n.html#//apple_ref/doc/uid/TP40008305-CH1-SW1

As well as the Basic Core Data section in the Cocoa Programming book I have.

That tutorial did a great job of showing the functionality, as well as showing me a few other things that I haven't done before (like the edit/delete combo button, and creating interface elements outside of interface builder).

Thanks for the help guys!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.