1

I created a game that involves the use of a dictionary. It has about 73000 words. However, after the review process the app got rejected. Here is the review comments:

"We found that your app crashed on an iPad running iOS 6.1.3" "The app crashes when tapping the play button." "Your app may encounter this issue if it is using too much memory."

I am stumped. No problem with the app on my iPhone running 6.1.3 or my iPad running 6.1.3. So I am assuming it crashed on an iPad mini. Is there a more efficient way/better place to load a dictionary into memory? This is how I currently do it after the play button is pressed. Thanks in advance!

    NSString *filePath = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: @"dictionary"] ofType:@"txt"]; //set where to get the dictionary from
    NSData* data = [NSData dataWithContentsOfFile:filePath]; //pull the content from the file into memory
    NSString* string = [[[NSString alloc] initWithBytes:[data bytes]
                                                 length:[data length] 
                                               encoding:NSUTF8StringEncoding] autorelease];//convert the bytes from the file into a string
    NSString* delimiter = @"\n";//split the string around newline characters to create an array
    currentDict = [string componentsSeparatedByString:delimiter];
    [currentDict retain];
PCoder123
  • 364
  • 2
  • 11
  • What is the size of the file containing your words? If it's less than about 1,000,000 bytes I'd suspect that your problem is elsewhere. (Did they send you any traces or dumps?) – Hot Licks May 16 '13 at 22:30
  • Have you run any profiling software on it? The instruments tool that ships with XCode has a tool called allocations that can give you some insights into where your memory is going... – isaac May 16 '13 at 22:32
  • The file is 1,745,228 bytes. Does this make a difference? – PCoder123 May 16 '13 at 22:33
  • Do you really need the whole thing loaded? You should certainly profile the app anyway. – Wain May 16 '13 at 22:35
  • Why don't you just use `stringWithContentsOfFile:encoding:error:` instead of first creating an `NSData` object and then converting it to an `NSString`. That would reduce the temporary memory usage (by about 50%), though I doubt that this is really the main problem here. A binary plist would be even better because then you wouldn't have to split the string every time you load it. – omz May 16 '13 at 22:51

2 Answers2

1

It doesn't seem to me as though 73,000 words would place a strain on memory, and it may be something else entirely. Run Instruments, use the allocations tool to monitor what's happening with your memory. Identify if it really is this dictionary that's at fault.

That said, the strategy you're using isn't great for a number of reasons (including the one you're suggesting it might be). There are a number of alternate approaches that you could use to let you get at the part of the dictionary you need at any given time versus your current approach, which as far as I can tell resides completely in memory all the time.

A simple solution might be to convert to an NSDictionary and load that from file. Another more complex but more efficient yet solution would be to roll out a pre-populated CoreData database (there are a number of existing solutions if you snoop around github for example).

isaac
  • 4,867
  • 1
  • 21
  • 31
  • It's not clear how loading an NSDictionary (or NSArray, which would make more sense) would be require significantly less storage. – Hot Licks May 16 '13 at 22:44
  • Thanks! I tried out Instruments, and it appears the Dictionary is the problem. I will try the CoreData Db. – PCoder123 May 16 '13 at 22:46
  • 1
    @HotLicks It wouldn't require less storage on disk, but it would probably be more efficient to load because you don't have to split the file's lines every time. With the current approach, you need roughly twice the amount of temporary memory because you have the source string (the entire file) and the array of lines in memory simultaneously. – omz May 16 '13 at 22:57
  • @HotLicks An array would certainly work, but when choosing a collection class to store a "dictionary", I fail to see how an array makes "more" sense than a dictionary class. – isaac May 17 '13 at 17:09
  • @isaac - The OP's original code is just producing an array. He's never specified what he's doing with this "dictionary", and since this is apparently just a list of words without definitions, it doesn't even fit an NSDictionary. A set, perhaps, but not a dictionary. – Hot Licks May 17 '13 at 17:51
  • @HotLicks Hmmm... OP headline is "How to load a Dictionary". There is no discussion of whether or not definitions are involved. Given the ambiguity, my answer presumes he meant what he said. If the question was "How to load a list", I would have suggested a set or array. – isaac May 17 '13 at 18:46
0

That seems like an exceptionally slow and memory intensive way to store 70k words.

I would recommend instead storing the whole dictionary in a small preloaded SQLite database, or at least a binary plist file - the database is really a better choice though as you can run searches without all the contents being in memory.

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150