Save Third party Library Custom Object to NSUSerDefault - iphone

So,I am using the AFPhotoEditorController and there is property of it named as AFPhotoeditorSession that stores and tracks all user action.THis session class is custom object that inherits from NSObject,I have googled about how to save custom objects in NSUser Defaults and came to know that We can save that class if that class conforms to protocol NSCoding ,I don't know that whether I can change this class,Because it is only.h file that I have in my custom framework of AviarySDk.
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:
[self.sessions objectAtIndex:0]]; // self.session an array of one object of AFPhotoeditorSession
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myEncodedObject forKey:#"myEncodedObjectKey"];
[defaults synchronize];
NSData *data1 = [defaults objectForKey:#"myEncodedObjectKey"];
AFPhotoEditorSession *obj = (AFPhotoEditorSession *)[NSKeyedUnarchiver unarchiveObjectWithData: data1];
NSLog(#"%#",obj);
I am getting error like :
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AFPhotoEditorSession 0x1c5fa0f0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key modified.'
And you can check the AFPhotoEditor Session class at PhotoEditorSession

You can make the class conform to NSCoding by declaring and defining a category which conforms to that protocol and implements the necessary methods.

Actually creating your own category means that you will have to have it compliant with that object as new ivars are added or changed, forever.
The right way to do this is to determine exactly what you would need to recreate an object of that class - the core values - then create keys and values for each and put them into a dictionary. Put the dictionaries into your user defaults. When you want to retrieve the values, pull out a dictionary, use those values to instantiate the objects.
The other option is to ask the author of AFPhotoeditor to do it, or do it yourself, and send him a pull request. But if you do it as a add on, you will have to update your category everytime the original framework changes.

Related

Storing complete class object into database in iPhone

I am new to this development.
I want to store complete object of a class into my database.
Actually I am creating application where user can add multiple views to parent view and want to save it, so that next time when user fetches it, he will get what ever he has saved i.e. views to parent view previously.
Any logic or suggestion on same will really be helpful,
Thanks in advance
Any object you want to save will need to conform to the NSCoder protocol. Keep in mind that if you have custom objects within your parent object that they to will need to conform to NSCoder. Add the following methods to your custom class(es).
- (id)initWithCoder:(NSCoder *)coder {
_inventory = [[coder decodeObjectForKey:#"inventory"] retain];
return self;
}
- (void)encodeWithCoder:(NSCoder *) encoder{
[encoder encodeObject:_inventory forKey:#"inventory"];
}
In the example above I want to encode a player's inventory. If the inventory contains custom objects (as opposed to a bunch of NSStrings for example) they'll also need their own NSCoder methods.
Below I turn it into something you can save out to NSUserDefaults. Adjust appropriately to store in a DB. Keep in mind if you want to send NSData over the wire to store in a DB you'll want to convert it to Base64 and possibly compress it.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData * encodedObject = [NSKeyedArchiver archivedDataWithRootObject:rootObject];
[defaults setObject:encodedObject forKey:kSaveArchiveKey];
[defaults synchronize];
To go the other way, you'll want to grab your NSData, do whatever magic on it as I described above (base64, compression) and unarchive.
PlayerInventory *inventory = [NSKeyedUnarchiver unarchiveObjectWithData:playerInventoryData]
You should choose between NSCoding and Core Data depending on your exact needs. See this post for more info: NSCoding VS Core data
You can store state(value of any attributes) of any object in database. You should use NSCoding.Example here

Using PLists for Persistence on iPhone

Simple question about property lists within an iphone app. I know you can read data in from a plist, but is there a way to write user-inputted data to a plist? If so, how? It's easy to find tutorials on reading information from plists, but I'm having trouble finding resources on writing to plists.
This is how I write data items to a plist:
[myPlistFile setInteger: myInt forKey: #"someKey"];
Of course, you can change setInteger with setBool, etc for different types.
Hope this helps!
--
Edit:
If your .plist was a member of an important class or similar...
Header of myClass:
NSUserDefaults* myPreferences;
#property (nonatomic, retain) NSUserDefaults* myPreferences;
.m of myClass:
self.myPreferences = [NSUserDefaults standardUserDefaults]; // load our preferences
[[NSUserDefaults standardUserDefaults] registerDefaults: [NSDictionary dictionaryWithContentsOfFile: [[NSBundle mainBundle]pathForResource: #"nameOfFile" ofType: #"plist"]]]; // now load the custom .plist file
In the docs for both NSArray and NSDictionary it shows they each have an instance method:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
For NSDictionary it describes this method as
Writes a property list representation of the contents of the dictionary to a given path.
For NSArray it says this in the discussion
This method recursively validates that all the contained objects are property list objects before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
So essentially both of these will write plist's if the items that they contain can be used in plists e.g. Array, Dictionary, Boolean, Data, Date, Number and String

NSUserDefaults: Question about difference between two approaches

Problem
I want to store a NSString in NSUserDefaults and retrieve it later. I have a question about two different retrieving methods. Now at the top of the file I have:
// String used to identify the update object in the user defaults storage.
static NSString * const kLastStoreUpdateKey = #"LastStoreUpdate";
Method 1
NSString *lastUpdate = [[NSUserDefaults standardUserDefaults] objectForKey:kLastStoreUpdateKey];
Method 2
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *myString = [prefs stringForKey:kLastStoreUpdateKey];
Are there are significant differences I should know about? Also, can someone please explain what exactly is objectForKey? Apple's API states: that it "Returns the object associated with the first occurrence of the specified default." What exactly do they mean by the "specified default?
Thank you!
Generally you should use method 1.
that is "objectForKey".
Because, you know that, whatever you have stored in NSUserDefault. So, at the time of retriving it, you can catch the object with proper class like NSString, Array or any other user defined.
genrally "stringForKey" is not used.
If you are storing ingteger, BOOL into NSUserDefault then you should use intForKey, BOOLforKey, etc..
Cheers.

NSUserDefaults overwriting new values with old

I have a bunch of userdefaults value that I use to load my UITableView in
-(void) prepareDisplay
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
table.dataSourceArray = [standardUserDefaults objectForKey:#"dataSource"];
}
-(void) viewDidLoad method
{
[self prepareDisplay];
}
and it works fine up to this point.
Then at a later point I change the userdefaults value and synchronize. Then I have to reload my table again. But before that I need to set the datasource array using the same
prepareDisplay () method.
Here I think that the instance of userdefaults that I created in my viewDidLoad earlier is overwriting or messing up with my userdefaults value and it calls up the old values again and not the newly set value.My newly set userdefaults value get overwritten with the old values. I have checked the plist file in the application sandbox after I do the userdefaults resetting and the values are reflected properly. But later, I don't how and when, they get overwritten with the old values. I am sure there is nothing I am doing explicitly to mess them up after resetting.
Can anybody help. Thanks
Actually you don't need an instance variable for NSUserDefaults because it is a singletone object. Avoid it. Additionally you may check the method - (BOOL)synchronize of the same object which Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.

Object from NSUserDefaults releasing?

So I have a username saved in the UserDefaults. For some reason, I am experiencing some strange behavior.
I have a data controller that goes and fetches some data from the server based on the user name.
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSLog(#"NSUserDefaults dump: %#", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
userID = [prefs stringForKey:#"username"];
This works fine for the first few times, but after I do some random stuff and go back to try and reload the views, it crashes. It says:
-[CFString retain]: message sent to deallocated instance 0x4b18ff0
This is strange because it is stopping on the NSLog line. Has anyone seen this before or know why it may be happening??
How you defined your userID? If it's a property with a retain attribute you should call
self.userID = [prefs stringForKey:#"username"];
this way your string will be retained automatically. The string that is returned from stringForKey is autoreleased.
stringForKey returns an autorelease object which you aren't retaining, it's probably released as soon as that method finishes.
You need to retain that string either by doing so manually or using a property declaration with the retain setting.
And then you need to release it at some point (at least in dealloc)