14

Recently, I'm a senior in high school, and I'm interested in making apps for iPhone. Recently, one of my apps came out: NBlock. It's a puzzle app and it's very challenging. However, it has a few problems. The high scores are not saved. I've been told to use a plist. Any tips?

icodebuster
  • 8,890
  • 7
  • 62
  • 65
Andrew
  • 708
  • 3
  • 7
  • 16
  • 4
    You could start by reading [apple's plist tutorial]( http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PropertyLists/QuickStartPlist/QuickStartPlist.html). – Jon7 Aug 14 '11 at 22:02

5 Answers5

12

The URL based method for this:

// Get the URL for the document directory
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSURL *documentDirectoryURL = [[fileManager URLsForDocumentDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0];

// Turn the filename into a string safe for use in a URL
NSString *safeString = [@"scores.plist" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

// Create an array for the score
NSMutableArray *array = [[NSMutableArray alloc] init];      
[array addObject:[NSNumber numberWithInt:score]];

// Write this array to a URL
NSURL *arrayURL = [NSURL URLWithString:safeString relativeToURL:documentDirectoryURL];
[array writeToURL:arrayURL atomically:YES];
Abizern
  • 146,289
  • 39
  • 203
  • 257
  • 1
    To me it seems much cleaner and clearer to use `-[NSURL URLByAppendingPathComponent:]` for file URLs instead of the relative URL. This would remove the need for percent escaping of the path and is generally less error prone. – Nikolai Ruhe May 27 '13 at 07:06
3

I'd avoid using a plist. The easiest way to save simple data in an application, by far, is NSUserDefaults.

Check out this tutorial for a simple guide on how to use NSUserDefaults. Always be sure to synchronize NSUserDefaults when you're done writing to them.

If you're looking for a more powerful (but more complex) way to save data, check out Apple's guide to using Core Data.

Community
  • 1
  • 1
mopsled
  • 8,445
  • 1
  • 38
  • 40
  • I thought NSUserDefaults was recommended for standardised default settings that you want to persist related to language preferences and the like? – cheznead Nov 13 '15 at 15:36
3

Heres what you want:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"scores.plist"];
NSMutableArray *array = [[NSMutableArray alloc] init];      
[array addObject:[NSNumber numberWithInt:score]];        
[array writeToFile:path atomically:YES];

And to add new scores do initWithContentsOfFile:@"scores.plist" instead of init in the declaration of array. You can optionally use NSUserDefaults.

Eric Platon
  • 9,819
  • 6
  • 41
  • 48
JonasG
  • 9,274
  • 12
  • 59
  • 88
  • 1
    Can somebody who's on a pc please format the source code in my post right? Its impossible on my ipod.... – JonasG Aug 14 '11 at 22:44
  • What do you mean by that? `writeToURL:automatically:`? – JonasG Aug 15 '11 at 00:11
  • 2
    But why would you need the URL method if you aren't actually writing to a URL?? – JonasG Aug 15 '11 at 01:31
  • Just because it's a local file doesn't mean that it is not a URL. IIRC the recommendation is to move away from path based file methods to URL based ones. Your answer is fine and works - I just wanted to show another way of doing the same thing using URLs instead of paths. – Abizern Aug 15 '11 at 01:34
2

Take a look into NSKeyedArchiver/Unarchiver. You can save pretty much anything you want; NSUserDefaults, in my experience, dumps your data if you kill your app from the tray. Core data is really used better if you're managing large amounts of data with databases such as sqlite.

Dylan Reich
  • 1,400
  • 2
  • 11
  • 14
  • 1
    I've never had that issue with a properly `synchronize`d `NSUserDefaults`. – mopsled Aug 14 '11 at 22:19
  • 1
    I'll look into that, thanks. NSUserDefaults is really only good if you're just saving a simple string or something like that (I guess the asker might be a good candidate), as long as it can be permanently saved. – Dylan Reich Aug 14 '11 at 22:23
  • Check out the link I added in my answer to see how to deal with that issue. – mopsled Aug 14 '11 at 22:27
0

I would say the below code will work and pretty straight forward unless custom object data types(Its a different story again) are used:

NSString* plistPath = nil;
NSFileManager* manager = [NSFileManager defaultManager];
 if ((plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"PathTo.plist"])) 
   {
    if ([manager isWritableFileAtPath:plistPath]) 
     {
       NSMutableDictionary* infoDict = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
      [infoDict setObject:@"foo object" forKey:@"fookey"];
      [infoDict writeToFile:plistPath atomically:NO];
      [manager setAttributes:[NSDictionary dictionaryWithObject:[NSDate date] forKey:NSFileModificationDate] ofItemAtPath:[[NSBundle mainBundle] bundlePath] error:nil];
     }
   }

setting the date attribute might be helpful to check when is the last time score was updated.

Dileep Mettu
  • 140
  • 12