Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

AppFusion - 6 in 1!
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 09-04-2008, 03:23 AM   #1 (permalink)
Registered Member
 
chuck's Avatar
 
Join Date: Aug 2008
Location: Berlin, Germany
Posts: 87
Default 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.
chuck is offline   Reply With Quote
Old 09-04-2008, 04:38 AM   #2 (permalink)
New Member
 
Join Date: May 2008
Posts: 49
Default

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.

Good luck with your application!

Hope that helps.

D
David H Dennis is offline   Reply With Quote
Old 09-04-2008, 01:01 PM   #3 (permalink)
New Member
 
Join Date: Apr 2008
Posts: 802
Default

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.
scottiphone is offline   Reply With Quote
Old 09-04-2008, 02:12 PM   #4 (permalink)
Registered Member
 
chuck's Avatar
 
Join Date: Aug 2008
Location: Berlin, Germany
Posts: 87
Default encode and decode methods

As requested, here is my code to encode and decode my dictionary entry object. Note that all of the variables are NSString. Very straightforward.

Code:
- (void) encodeWithCoder: (NSCoder *) encoder {
	[encoder encodeObject: self.traditional];
	[encoder encodeObject: self.simplified];
	[encoder encodeObject: self.pinyin];
	[encoder encodeObject: self.english];
}

- (id) initWithCoder: (NSCoder *) decoder {
	self.traditional = [[decoder decodeObject] retain];
	self.simplified = [[decoder decodeObject] retain];
	self.pinyin = [[decoder decodeObject] retain];
	self.english = [[decoder decodeObject] retain];
	
	return self;
}
chuck is offline   Reply With Quote
Old 09-04-2008, 04:12 PM   #5 (permalink)
New Member
 
Join Date: Apr 2008
Posts: 802
Default

try something like this:

Code:
- (void)encodeWithCoder:(NSCoder *)encoder {
	[encoder encodeObject:textString		forKey:@"TextString"];
...
- (id)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
	 	
	 		[self setTextString:[coder decodeObjectForKey:@"TextString"]];
...
if you set up properties you don't have to deal with retain in your code.
scottiphone is offline   Reply With Quote
Old 09-04-2008, 04:18 PM   #6 (permalink)
Tutorial Author
 
Join Date: May 2008
Posts: 315
Default

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.
Code:
- (void) encodeWithCoder: (NSCoder *) encoder {
	[encoder encodeObject: self.traditional forKey:@"traditional"];
	[encoder encodeObject: self.simplified forKey:@"simplified"];
	[encoder encodeObject: self.pinyin forKey:@"pinyin"];
	[encoder encodeObject: self.english forKey:@"english"];
}

- (id) initWithCoder: (NSCoder *) decoder {
	self.traditional = [[decoder decodeObjectForKey:@"traditional"] retain];
	self.simplified = [[decoder decodeObjectForKey:@"simplified"] retain];
	self.pinyin = [[decoder decodeObjectForKey:@"pinyin"] retain];
	self.english = [[decoder decodeObjectForKey:@"english"] retain];
	
	return self;
}
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.
Code:
NSMutableData *theData = [NSMutableData data];
NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];

[encoder encodeObject:wordArray forKey:@"wordArray"];
[encoder finishEncoding];
[theData writeToFile:yourFilePath atomically:YES];
[encoder release];
Then, you can read it back in your applicationDidFinishLaunching method like this.
Code:
NSData *theData = [NSData dataWithContentsOfFile:yourFilePath];
NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
wordArray = [[decoder decodeObjectForKey:@"wordArray"] retain];
I did a tutorial over how to use NSKeyedArchivers and NSKeyedUnarchivers, which can be found in the tutorial section.
myersn024 is offline   Reply With Quote
Old 09-08-2008, 05:25 PM   #7 (permalink)
Registered Member
 
chuck's Avatar
 
Join Date: Aug 2008
Location: Berlin, Germany
Posts: 87
Default

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!
chuck is offline   Reply With Quote
Old 11-23-2008, 05:55 PM   #8 (permalink)
Registered Member
 
Join Date: Aug 2008
Location: The Netherlands
Age: 30
Posts: 86
Default encoding/decoding objects with mutablearray as property

Hi i've been searching quite some time for an example of how to encode/decode the following structure:

@interface myDataModelType : NSObject {
//datafile versioning properties
double dataVersion;

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..
__________________
EeKay Sez:: : :

0110100001100101011011000110110001101111 to you !

WwW : www.eekay.nl
mniE : www.mynameise.com/eekay
Twitter : www.twitter.com/eekayonline

Last edited by EeKay; 11-30-2008 at 11:45 AM.
EeKay is offline   Reply With Quote
Old 01-05-2009, 04:14 PM   #9 (permalink)
Registered Member
 
Join Date: Oct 2008
Location: Switzerland
Posts: 34
Default

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.
sirenum is offline   Reply With Quote
Old 01-05-2009, 04:34 PM   #10 (permalink)
Registered Member
 
chuck's Avatar
 
Join Date: Aug 2008
Location: Berlin, Germany
Posts: 87
Default

Quote:
Originally Posted by sirenum View Post
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!
__________________
German Course: Learn German anywhere! Chess Player: Study Chess anywhere!
chuck is offline   Reply With Quote
Old 04-07-2009, 10:04 AM   #11 (permalink)
New Member
 
Join Date: Jan 2009
Posts: 2
Default Beaten to the Punch...

Quote:
Originally Posted by chuck View Post
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.
mtwagner is offline   Reply With Quote
Old 07-22-2011, 01:02 PM   #12 (permalink)
Registered Member
 
Join Date: Jul 2011
Posts: 42
Default

Quote:
Originally Posted by chuck View Post
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!
xcoderx is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 623
21 members and 602 guests
ADY, bandley, BrianSlick, Creativ, dacapo, Dattee, djbrooks111, gbenna, HDshot, IphoneSdk, iseff, jakerocheleau, jbro, joeallenpro, linkmx, mer10, nimesh_158, Reyna, ukneeq, yurikus
Most users ever online was 1,187, 10-11-2011 at 08:09 AM.
» Stats
Members: 160,619
Threads: 89,833
Posts: 383,490
Top Poster: BrianSlick (7,244)
Welcome to our newest member, yurikus
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 04:46 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0