Is it possible to save to NSUserDefault before first run? - nsuserdefaults

I want to save a custom object array as NSData to NSUserDefaults that will be available at first run, is it possible? if so, how?

You should use the -registerDefaults: method to set any default values that you would like to have available before the user has set anything.

Related

Best Way To Store Multiple Arrays Associated Together - Objective C

Throughout my iOS program. I create multiple arrays that all work together to make the program work. Now I need a method to store the arrays even when the iPhone is turned off. So I need these arrays to be stored like files that only I can touch.
I really would like to use User Defaults, but I just don't know if that is what I need. I have questions like:
How long will my data last in User Defaults?
When could you possibly lose the data?
If I was able to store arrays in User Defaults, how might I go about storing arrays in NSDictionaries? That way I could keep of my associated arrays together and give each array a specific key.
store array as NSData as in NSDefaults
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:urArray1] forKey:#"Array1"];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:urArray2] forKey:#"Array2"];
and read it as
NSData *dataRepresentingSavedArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"Array1"];
if (dataRepresentingSavedArray != nil)
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
I think that what you want is to store the arrays on the disk and then (when you actually need them) get them back. You can start by seeing if the objects inside your NSMutableArrays conform with the NSCoding protocol. You can then simply write them to disk and load them when you need. For that you can use NSKeyedArchiver class.
As #The Saad pointed, and well, you can store the arrays using that piece of code. Although I wouldn't recommend it. You can check #roronoa zorro answer, as well.
NSUserDefaults basically just a wrapper around property list serialization.
NSUserDefaults provides a programmatic interface to Mac OS X's
preferences system. preferences are actually stored to the disk, they
are written to the user's Library/Preferences/ directory with the file
name equal to the bundle identifier with a plist extension.
Take a look at MikeBeam's article here
Well NSuSerDefaults is a way of storing persistent data in iPhone and you don't have to worry about losing of data or about it's persisitency as long as the application remains on the iPhone.
Yes, you can store the NSDictionary object in NSUserDefaults but it is advisable to use it for small Data.For bigger data you can use sqlite or any other DB.
Here's the Tutorial For NSUserDefault

Save image on disk and associate it to managed object iphone

I need to save an image picked by an image picker on disk and than associate it to a managed object.
I want to store the image path in the managed object (imagePath attribute is nsstring) but I don't know how to call the image because it must be always available until user delete the managed object.
I thought to call every image with managed object's ID but I believe that it is too long and it's still temporary when I try to save my image...
How can I call every image for each managed object?
Thank you!
If you are going to store it on disk why not just store it in core data using the Transformable type.
You can shorten the managed object id using something like:
NSString *_id=[[self.objectID URIRepresentation] lastPathComponent];
Using the managed object's ID turned into a file name string is actually ideal since it is guaranteed to be unique. The length of the name is hardly an issue to the file system.

NSUserDefaults setObject and IntegerForKey, use on the same key, if not how can I workaround?

I need to iterate through all the keys in my NSUserDefaults and transfer them to another format. Later I'll want to transfer them back, programatically.
I have a lot of keys and I have no way in my naming convention or by other means to determine if I used setObject or setInteger etc.
If I use setObject will this enable me to use integerForKey on that key ?
If I can't want can I use instead?
No, you should not be able to get the correct objects if you use integerForKey:. However you could get the correct objects if you use objectForKey:. This is because if you had used setInteger:forKey:, it automatically calls setObject:forKey:. So, there will be an object for the key. So what you have to do is iterate through the keys, get the objects using objectForKey: and convert it to the data type that you want.
I'm pretty sure using setObject will allow you to use integerForKey later.
Another way to go could be by adding a plist to your project and store everything in there. It's basically the same as NSUserDefaults is doing, only you'll be doing it all by hand. You can just read the contents of a plist to either an NSArray or an NSDictionary (whichever you chose to construct it with in the first place) and then access the members you need from that object.
Hope this helps.

How to save and retry reporting GKAchievement's after network failure?

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:

NSUserDefaults: What's the +resetStandardUserDefaults method good for? How can I provide "system settings"?

I want the user to be able to make some preferences like colors, prefered images, etc.
When I use NSUserDefaults for this, on first start of the app there will be no preferences, right? So, every time I want to get a preference like
NSInteger avatarID = (NSInteger)[[NSUserDefaults standardUserDefaults] objectForKey:#"avatar"];
I have to check if it's null, and then use my system preference. But then I've seen this in the docs: +resetStandardUserDefaults
Are there two branches of defaults saved somewhere? The ones from the user, and the ones from the developer?
Yes, but it's a little different than what you're doing. NSUserDefaults has the registerDefaults method, which lets you populate the "blank" defaults from an NSDictionary with values you provide. Put this in the +initialize method in your app controller, and you'll know the default values are sensible. If the user defaults object finds a "real" value for a key, either one you set during the current application launch or loaded from disk, it will always take precedent over what you provided in registerDefaults. resetStandardUserDefaults will remove the shared user defaults object from memory and undo any customization you've made to it, it's not something you'll need to provide default values.
Also, keep in mind you can't just cast an object to a primitive NSInteger value as you're doing, you'll just end up with a number representing the memory location of the object's pointer. Either use NSUserDefault's integerForKey: to get a primitive directly, or use objectForKey: to get an NSNumber and use integerValue to get the primitive value.