archiving an object? (NSKeyedArchiver, SQLite or CoreData)
I'm writing a dictionary application and the source of my dictionary is a txt file, but I need to either parse it into an array of DictEntry [custom] objects or put everything into a read-only database. Currently I take the dictionary from the file, split it by line and then parse each line, but while this works fine in Simulator, it is VERY slow in the iPhone (about 30 secs to load or so, unacceptable for a dictionary). The dictionary text file itself is 4.5 MB.
Now, I thought of serializing my DictEntries array to a file, but found that object serialization is deprecated in preference to object archiving with NSKeyedArchiver. Even though I have encodeWithCoder and initWithCoder functions in my DictEntry class, it still doesn't work. It says "Archiving SUCCESS" even though it doesn't seem to write anything:
Code:
dictEntries = [[NSMutableArray alloc] initWithCapacity:71080];
// -snip- Code to put stuff into array is here
NSString *arrayPath = (NSString*)[[NSBundle mainBundle] pathForResource:@"DictEntries" ofType:@"arch"];
if ( [NSKeyedArchiver archiveRootObject:dictEntries toFile:arrayPath] == NO ) {
NSLog( @"Archiving FAIL!" );
} else {
NSLog( @"Archiving SUCCESS!" );
}
I'm considering going with an SQLite database, but since everything works in an array of objects already, I don't really see the point. Is there some easy way to archive an array of custom user-defined objects to a file that I'm missing? I also tried [dictEntries writeToFile:arrayPath atomically:YES] but it returns fail.
Any more ideas? Perhaps the application bundle is read-only? I've already wasted a few good hours on this... Any help would be greatly appreciated.
If you are loading 4.5mb of stuff into your application, it will crash, because iPhone applications can only use about 2mb of heap space before getting out of memory errors. These problems don't show up in the simulator because it has all your computer's memory at its disposal.
A sqlite3 database will probably work because you have a relatively simple application, but it will chew up a lot of memory and not give it back unless you're very careful. For each query you use, create a query handle (sqlite3_stmt) with the prepare API function, and save it into a global variable. Then reset that query when you are done, and re-run step when you want to run it again. This works but still seems to use up much more memory than is seemly. Creating ad hoc queries using sprintf() guarantees that your application will run out of memory and crash.
My iTrivia application (which you can buy from the app store starting today- hurrah!) works that way.
For a dictionary, I might recommend a simpler solution, as long as the number of words is not that high. Load the words and a record ID number into an array of objects. Then make the definitions files in your app bundle that are named after the ID number. For instance, record ID 10 would be 10.html .
This will give you blazing fast searches, since the words are in memory, and quick loads of the definitions into the web view because web views are designed to be used that way.
While developing my HauntFinder application (not yet submitted), I discovered that in a situation like this incremental search works great - that is, instead of waiting for someone to press the search button, take each character and have it search right away. So you type "d" and you get "dog", "domestic" and "diddle"; then type "o" and get "dog" and "domestic" and "m" and get only "domestic". It's actually quite surprising how few characters you need to zero in on the word you want.
This probably seems like a slightly bizarre way to work, since if you're like me you're spoiled by easy access to SQL data from other programming environments, but I can tell you that it will work, and look great to your end user.
Archiving works but you don't show the code. If it's a standard array with standard objects you shouldn't have to write encode/decode.
Side note: There's no fixed heap size to my knowledge. The amount you get available varies a lot and if you use any system services (taking photos, etc) they chew up a lot of your available space.
I use NSKeyedArchivers and NSKeyedUnarchivers for all of my saving needs at the moment, and I see one difference between what you're doing and what I'm doing. I know that you can just call encodeObject, but I've never had much luck with that. You might try something like this.
You may have to change your code to save the data as well. Something like this in your applicationWillTerminate function should work. wordArray is the array that holds your dictionary info when it's read into memory.
Just to inform you, I tried using the NSKeyedArchiver, but then found that my data would bloat from 4.5 MB to 11.3 MB, so that's not a viable option. Then I tried simply changing my source format to a tab-delimited file, but it's still loading way too slowly (about 20 secs, unacceptable). Tomorrow I'm going to just make my app work with a database.
In any case, learning how to properly encode and decode objects will prove really useful in future projects for me! Thanks everyone for all your help!
NSString *name;
int ID;
BOOL someBool;
NSMutableArray *myMutableArray;
}
I got this working as far as that it encodes/decodes objects of this class.
I can both encode/decode the name, int bool. but i cannot find any example that makes clear to me howto decode/encode the mutablearray property of this class...
i tried with decodeObjectForKey but this does not return me "the array object" with alle the records.. i red from the documentation that pointers aren't encoded, but i cannot find anywhere how it IS done instead..
Anyone succesfully implemented this? Thanks in advance..
EDIT: as it seems.. i had other bugs in my App. fixing them showed me that archiving an array as object was the way to go..
Hey Chuck
Have you had any success with the database approach? If yes, how did it affect your application load time?
I'm asking because I'm thinking about switching from NSKeyedArchiver/Unarchiver to sqlite myself.
Hey Chuck
Have you had any success with the database approach? If yes, how did it affect your application load time?
I'm asking because I'm thinking about switching from NSKeyedArchiver/Unarchiver to sqlite myself.
I actually gave up on my project, because someone released basically the same app I was planning to sell, but made it free, thus making it pointless for me to continue working on that project. Good luck to you though!
I actually gave up on my project, because someone released basically the same app I was planning to sell, but made it free, thus making it pointless for me to continue working on that project. Good luck to you though!
I've found that has happened to me a few times. I'm also working on a C/E dictionary. I use a few different ones, but none have ALL the features I want so I continue with mine. If nothing else competition is a good thing. (I find nobody updates their dictionary data sets very often. Also I enjoy the mental exercise. And why spend $2 when you can spend countless hours making your own.
I actually gave up on my project, because someone released basically the same app I was planning to sell, but made it free, thus making it pointless for me to continue working on that project. Good luck to you though!
are you retarded?? It doesnt matter if someone already put out the same app if your looks and works better people will still purchase it!