I am writing this game with hundreds of levels, but in one of my menus I want to let the user 'quick select' any level by pressing the icon for it (like springboard, except instead of apps, ill have levels). But I also want a little tick to show up in the icon if the level has been completed.
What is the best way of checking which (of my 300+ levels) has been completed, in a totally different file?
NSUserDefaults seems a very clumsy way of doing this. I was thinking more like a loop? But I have no Idea how to do it.
Thanks for your help!
You can always store NSArray object in NSUserDefaults. It could be either boolean array indicating whether level completed or not, or just the list of completed levels.
Creating a separate file for it seems like too much hassle to me.
You can find the list of things you can store in NSUserDefaults in its documentation.
edit
Array of booleans could be created like this (since bool is a primitive type, we wrap it into NSNumber)
NSMutableArray *passedLevels = [NSMutableArray array];
[passedLevels addObject:[NSNumber numberWithBool:TRUE]];
if ([[passedLevels objectAtIndex:0] boolValue]) {
// level passed
}
You can find more methods to manipulate NSArray and NSMutableArray in their documentation.
Related
In a certain view I have a bunch of AVAudioPlayer properties, each one is supposed to be played upon a certain user action. While the selected AVAudioPlayer is played, if another AVAudioPlayer was played - it should stop.
To manage that, I've created an Array that holds all the AVAudioPlayer properties and upon user selection, before playing the selected AVAudioPlayer, I wish to go over all the AVAudioPlayers and stop them.
The problem is that the reasonable place to create the Array is at the beginning (let's say, in ViewDidLoad) and at this point none of the AVAudioPlayer properties went through alloc+init - so if I look at the Array in the debugger it shows as empty (number of objects = 0). Currently, I do the alloc+init action only when the user is actually selecting a certain AVAudioPlayer.
I can do alloc+init for all the AVAudioPlayers at the beginning as well, but that will take resources that are not necessarily required.
Is there a way to create this Array without taking the required resources? i.e. create the array with "empty" objects and later have them be allocated and initiated?
I have a similar situation. What I've been doing is:
NSArray *myArray = [NSArray arrayWithObjects:#"",#"",#"",#""];
in viewDidLoad (if my array is going to have 4 objects). Then as I have the information available, I do:
[myArray replaceObjectAtIndex:myLocationToAddValue withObject:myObject];
I got the idea for this looking at some code in a very old project written in a completely different language by someone else from my company. It seems to be working for what I need, and it does have the added benefit that I can loop through my array and check
if ([[myArray objectAtIndex:i] length] == 0)
to see where I have items already. I should note that the objects I'm adding are going to all be NSStrings - if this loops through and finds an object has been put into the array that isn't a string (or, more generally, doesn't have a "length" method), I'm guessing some nasty stuff would happen, but I haven't checked for that yet.
I'm certain there must be a much better solution, but I'll put it out there since there haven't been any answers to this yet. I figure a sloppy answer that seems to be working is better than no answer.
In my game I want to save a set of integers as statistics players can view. E.g number of deaths. This is an int I simply increase by one each time they get a game over.
How can I save this then have it at that number when I relaunch the game?
Thanks.
EDIT:
Ok after reading a few answers Im thinking writing to a plist is the way forward. I have been looking at tutorials but lets say I try this:
scoreData *score = [scoreData sharedData];
[dictionary setValue:score.highScore forKey:#"key2"];
[dictionary writeToFile:#"stats.plist" atomically:NO];
I have accessed my singleton with my score inside. Now when trying to setValue I get an error saying Im trying to convert an int to object.
Im not sure how else to approach it. It seems simple enough, however everywhere I look seem to give essentially the same approach.
Thanks for the help thus far, anymore is appreciated.
I would not abuse NSUserDefaults (Apple discouraged this at WWDC this year). Instead why not simply create an NSMutableDictionary and then store NSNumber objects in it. The MutableDictionary can easily be written to file and as is easily read in.
Any number of a lot of ways.
If you are only saving this and maybe a couple other simple things, using user defaults is probably the best idea.
If however, you are saving a lot more items than just a few, you may want to either use your own property list (if the number of items is less than 200 or so).
If you have a lot of settings, I generally advise folks to look at Core Data instead. It's fast with lots of items, whereas the other two, not so much.
Try...
[[NSUserDefaults standardUserDefaults] setInteger:highScore forKey:#"HighScore"];
highScore = [[NSUserDefaults standardUserDefaults] integerForKey:#"HighScore"];
You can write to a file (i.e. plain C functions fopen() etc), can use your own classes and use NS(Keyed)Archiver, or use NSUserDefaults to save data.
Apple states that if you want to report a GKAchievement but you get a network error, the best way to handle this is to save the GKAchievement (possibly adding it to an array), then periodically attempt to report the achievement.
What is the best place to save the achievements? Would NSUserDefaults suffice, or would a property list be a better way?
When and how often should I attempt to report? On application launch, or something like every 10 minutes?
A property list can only handle specific classes (see "What is a Property List?"), which GKAchievement is not one of. NSUserDefaults uses property lists, so that's also out. GKAchievement does, however, conform to the NSCoding protocol, which means you can easily save them to disk using an NSKeyedArchiver. I would create an array of unreported achievements and read/write them like so:
//Assuming these exist
NSArray * unreportedAchievements;
NSString * savePath;
// Write to disk
[NSKeyedArchiver archiveRootObject:unreportedAchievements toFile:savePath];
// Read from disk
unreportedAchievements = [NSKeyedUnarchiver unarchiveObjectWithFile:savePath];
You can pretty much save anything in a property list (and thus NSUserDefaults) by turning it into NSData: archivedDataWithRootObject:
As all who usually ask such questions I'm newbie in iPhone SDK programming and I've spend realy a lot of time to find the solution by my self.
So, I need to save a lot of app data of diff datatypes (bool,string,int,float,double,int arrays,double arrays and arrays of pointers) to file. There're many forms with fields, app settings etc. All that I need to save either user quit the app, or it was terminated unexpectedly. User could work with as much forms with fields, as it's possible. File is needed to open project with all filled forms and app sets on other device.
My trouble is that I couldn't find in what way I should wrilte all that data to file. I tried two diff ways. 1st: fill array with form's data, fill NSMutableArray with such arrays for every form. But for NSMutableArray there's a method (void)addObject:(id)anObject, and I didn't find how to get that (id)anObject from every array(or anything else) to add items.
The 2nd I've tried to use: NSMutableData. The same troubles: to fill with my data I need to convert them to Data ((void)appendData:(NSData *)otherData). In both cases objecs of that classes couldn't be filled correctly with my data. And I can't save it to file.
Maybe there's some better solution? Will be very apreciative for any help.
NSNumber is usually the way to go for basic stuff (integers, bools, and doubles/floats/etc). For example:
NSNumber *aBool = [NSNumber numberWithBool:YES];
NSNumber *aFloat = [NSNumber numberWithFloat:1.0f];
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
[settings setValue:aBool forKey:#"some_key"];
The strings you can just add to NSUserDefaults because they are already objects (that conform to NSCoder, I believe), and for the NSArrays, just use the writeToFile: method:
NSArray *someArray = [NSArray arrayWithObjects:#"foo",#"bar",#"etc",nil];
[someArray writeToFile:#"filename" atomically:YES];
Some kind of serialization available in iPhone OS? Is that practically possible or should I quickly forget about that?
I am making a tiny app that stores some inputs in an NSMutableArray. When the user leaves, the inputs should stay alive until he/she returns to continue adding or removing stuff to/from that array.
When the app quits, there must be some way to store all the stuff in the array in a file. Or must I iterate over it, rip everything out and write it i.e. comma-separated somewhere, then the next time go in again, read the stuff in, and iterate over the lines in the file to make an array with that data? That would be hard like a brick. How to?
The easy way, since you already have an NSArray object is to write the array to disk using
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
and read it back in with:
- (id)initWithContentsOfFile:(NSString *)aPath
or
+ (id)arrayWithContentsOfFile:(NSString *)aPath
You can also use NSCoder.
You can probably search sof for the right code.
So long as the objects in the array implement NSCoding (NSString and NSValue do; if you're storing your own objects it's relatively straightforward), you can use:
[NSKeyedArchiver archiveRootObject: array toFile: filePath];
to save and:
array = [NSKeyedUnarchiver unarchiveObjectWithFile: filePath];
to load.
You can similarly load/save to NSData.
The iPhone SDK is designed to store data using SQLite tables.
You can use NSPropertyListSeralization, since NSArray is a type of property list. You can find more information here.