Grabbing text from files - iphone

Still working my way through this program. Next task on my to-do list is selecting random words from a pre-generated list. I've got the randomisation code sorted, but I now need to know the best way to store and retrieve words from my big list (and it is a fairly big list - over 220 words).
Since I'm designing for iPhone, memory is a paramount concern. Because of this I was hoping to avoid loading the whole file into memory. I'd much rather have the file laid out so that I can jump straight to an indexed position in the file and grab only the data I need. It would be nice if I could make use of the text file I already have with all the words in it, but I don't mind converting if there is benefit to some other method.
Anyone got any suggestions about the best way to do this?
-Ash

Well, 220 words isn't exactly a big list :-) Let's say each word is long, say 20 characters. Then you're talking about a measly 4.4kB. So I wouldn't worry about the size here. As Kevin pointed out, [NSArray arrayWithContentsOfFile:...] is likely the easiest way (also have a look at [NSDictionary dictionaryWithContentsOfFile:...]).
But if your list is getting really big (say 10000 words) then I'd suggest you read up on SQLite which is also supported on the iPhone.

Don't worry about the storage space (the storage required is far less than you think). Use a PLIST (File > New File > Resource (Mac OS X) > Property List), and arrayWithContentsOfFile to make loading the words simple (define an array as the root item in the PLIST; Apple's documentation has further details). Then, simply:
srandom(time(NULL));
NSUInteger index = rand() % [array length];
NSString *word = [array objectAtIndex:index];

Related

how can I simply store level data as an array and load it again?

I admit I am a newbee, although I have been writing this for 1.5 years now, I still feel as a beginner sometimes.
I am trying to write an action game with a spaceship flying through different levels.
For a while, it was sufficient to store the level data in UserDefaults, but now I would like to edit several levels and thus need a broader approach.
So I am basically using the same way of storing the data as I did before, which seems to work fine - it is saved, I can see it and read it.
For the storage, the data (Int64 values) is written to a long array, called LevelSave, then written to 'savestring' and finally saved as 'Level1'
var savestring : [AnyObject?]
savestring = LevelSave as [AnyObject?]
let objCArray = NSMutableArray()
objCArray.add(savestring)
objCArray.write(toFile: getFilePath(fileName: "Level1"), atomically: true)
However, when I can't seem to get beyond the point where I load the data:
if let _ = FileManager.default.contents(atPath: getFilePath(fileName: "Level1")) {
let arrayb = NSArray(contentsOfFile: getFilePath(fileName: "Level1"))}
It is somehow stored in the NSArray, which I can't properly access. I mean, I can print out the array as a whole, but cannot access the individual elements, not even the number of elements required to set the dimensions for the required array to work with.
I have searched for this question a lot, but it seems there is no-one fighting with a similar issue.
I don't want to get into too much detail with NSArray, I hope this is the only time I need it.
Does anyone know how to solve this?
Ok, I did it. A workaround though.
I converted the array to a text-string, to which I could add all elements. And saved that string.
After loading the file, I convert the string to separate string components, and then convert those string numbers into the good old integers, one by one in a for-in-loop.
It works.
Anyway, the documentation (particularly that from Apple) for these very complex matters is often so poor, that it drives me mad and from time to time I am thinking about quitting.
Stackoverflow.com is a great institution, thank you for that. Keeps me going!

Parsing XML using GDataXML returns a NSString object with a retainCount of 95.How to ensure it gets released?

The NSString object that is got by the following code has got a retainCount of 95.
for(GDataXMLElement *ele in [doc.rootElement elementsForName:#"myKey"])
{
NSLog(#"myKey %d",[[[ele.children objectAtIndex:0] stringValue] retainCount]);
[myDict setObject:[[ele.children objectAtIndex:0] stringValue] forKey:#"myKey"];
}
. so would it get released later when
[myDict removeAllObjects];
[myDict release];
is called.
the problem i am facing is that i have hundreds of strings like this parsed.... and all their retaincounts are around 95...would these strings get released?
the problem i am facing is that i have hundreds of strings like this
parsed.... and all their retaincounts are around 95...would these
strings get released?
First, retainCount is useless. Don't call it. No, really, don't use retainCount.
To answer your question, look to Instruments. Do the objects that you expect to go away actually stay in memory? If so, then turn on reference count tracking and see what still holds references to them (or what retains are unbalanced).
More likely than not, the XML subsystem is unique-ifying the strings such that only one copy of what may be repeated hundreds of times is in memory. That one copy may be retained dozens or hundreds of times as a result. When you removeAllObjects from myDict, there may still be a reference to the objects. It might even be an autoreleased reference and, thus, will actually go away.
The only way to know is to look to see if the objects are deallocated via Instruments (or some other means).
As per the definitions & explanations given by many others including raywinderlich in his How To Choose The Best XML Parser for Your iPhone Project.
GDataXML is nothing but a NSXML style DOM XML parser for the iPhone, developed by Google as part of their Objective-C client library. Consisting of just a M file and a header, it supports both reading and writing XML documents and XPath queries.
A DOM parser reads the entire document and builds up an in-memory representation that you can query for different elements. Often, you can even construct XPath queries to pull out particular pieces.
So it just creates a tree like structure for the given entire XML, each elements can be queried to pull particular pieces.
And as we know this all works with the pointers, so what ever elements we get from this tree will be just pointing to that object, with the same name(used while initializing xml) or a new name while pulling particular pieces(using NSXMLElement).
And so everything will be retained until we release the XMLDoc while initializing XML.
If you want we can check the retain counts after releasing the XMLDoc(but it may give crash as are we using released object).
I think it works in this way, if you or other developers have any other info on this share your info.

Parsing multiple XML web file iphone

Let's say i have a xml file with a tag named which contains the number of fields i want to show in my tableView and in another xml file i have the information to be displayed in that tableView.
The question is : Should i create 2 different file in my project (xmlparse1.h and .m + xmlparse2.h and .m) or should i just put all my code in 1 (xmlparse.h + .m) and differenciate which file i am parsing at the moment with a bool or something like that in the code?
I am developing an iphone app on Xcode 4.3 mac os x 10.7.4 if this might change
EDIT: 1st file :
<MenuPrin>
<humidite>82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0</humidite>
<tempmoy>
189,124,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700
</tempmoy>
</MenuPrin>
2nd File :
<Instal>
<nbrField>2</nbrField>
</Instal>
So it looks like this. So, since nbrField is 2 I would take the 2 first value from tempMoy and humidite and show them in a tableView.
END OF EDIT
If how you're parsing is similar in both instances, to add two sets of files that do effectively the same thing would be extremely inefficient and considered bad practice. It makes a lot more sense to create a parser that can handle the two different files than to write two parsers that can only handle a specific file each.
To more specifically answer your question, I would determine which file you are parsing and behave accordingly, whether you do this with a bool or something else is up to you.
EDIT: Here is the idea that just popped into my head, so if for whatever reason this wont work for you(Like I said its been a while), or someone has a better idea, I'm all ears. You could still have a set of files(.h and .m) that contain the definition of your parser. Your parser could contain within it a two variables of type Object1 and Object2 which are built in such a way that they resemble the data structure that you need to store what you parse once for your first type of file, and a different definition for your second type of file. This way when parsing once you determine which file it is you are reading, it just changes which of these two objects you write into. There are also plenty of variations for how you could set this up, and I can also think of a few cases for what you might be trying to do where this might not work, but there is the idea regardless.
If you think that the two sets of files approach is better for the application you are trying to write and makes more sense to you, given what has been discussed in the comments, it isn't necessarily a bad idea.
In case if u want to create two table view in one view u need to create a single .h & .m file...If u want to create individual table view u need to create two .h & .m...
Try TBXML parser...that is the easiest way and less memory usage for xmlparsing...

NSArray of values, want to display alphabetically in sections. How to distribute in correct sections?

Sorry, I'm not sure how to search for the answer to this, but I'm sure it's out there.
I have a large NSArray of strings in alphabetical order. I want to add them to a uitableview and have them distributed correctly in each section by the first letter. I have the sections set up, but I'm not sure how to tell my tableview to add to the next section when the object starts with the next letter in the alphabet. Thanks for any help! It's much appreciated!
Hy
You must parse the array manually, and then tell the tableView - via delegate method - the number of sections, and items. If I were you, I would place it in a dictionary, and the keys are numbers, which are represents sections, and the values are an array of the titles. It is easy to use. You only have to parse the original array.
There is an example that describes what you want:
http://www.devx.com/wireless/Article/43374/1763
I think using an NSDictionary is much more convenient in this case. An NSDictionary inherently allows you to store your data alphabetically.
Vocabulous is a great example project for this use case.

Creating and storing a prefix tree on iPhone before runtime

I'm currently making a word game for iOS that, when loading, reads in a text file of around 30000 words and loads them into a prefix tree for quick searching during gameplay. This works well, but the loading and tree construction process adds a noticeable few seconds to the app's startup time. At the moment I'm testing on an iPhone 4, but I imagine it would be a good deal slower on a 3GS earlier models.
Is there a way to create this tree at compile time rather than when the app opens? Or, less ideally, would it be possible to prebake the data with another program and add that file to the project instead of doing it at runtime? How would I go about doing that?
I run into the same issue with a game we developed, and for us, it performed better to use a SQLite DB with the words instead of the in-memory tree. The DB used less space than the plist that represented the tree, it did not require us to preload it in memory, and the performance (when querying for a valid word) was about the same.
pgb's answer is good. If you do not want to use SQLite, you can store your data in a plist and have [NSDictionary dictionaryWithContentsOfFile:] create a tree for you.
If you do choose to have the data compiled into your program, it will have to be built of primitive types, such as numbers and characters. Then, use structures and arrays to define the structure, and use a constant variable to store the data. Here is a simple example which is just an array of character strings:
const char *words[] = {"Word1","Word2","Word3"};
const unsigned numWords = (sizeof(words) / sizeof(char*));