Cache custom class - objective-c

In my app I am working with the SimpleKML framework
https://github.com/mapbox/Simple-KML
I have some big files which takes about 5 seconds to process thought this library. I was thinking to cache the object in something like NSData.
I have read this tutorial from Apple:
https://developer.apple.com/library/mac/#documentation/cocoa/conceptual/Archiving/Articles/archives.html
But i dont really know of using nscoder is the best way to do this. Can someone point me in the right direction?

You want to use NSKeyedArchiver and NSKeyedUnarchiver.
If the object you're saving (and the objects it has as properties, and their properties, etc.) implement the NSCoding protocol then it's, as simple as
NSData *savedData = [NSKeyedArchiver archivedDataWithRootObject:someObject];
[savedData writeToFile:pathToSaveFile atomically:YES];
to archive the object into an NSData and then save it to disk, and then later
NSData *loadedData = [NSData dataWithContentsOfFile:pathToSaveFile];
SomeClass *foo = [NSKeyedUnarchiver loadedData]
to load the data and unarchive the object from the data.
If not, you'll need to override initWithCoder: and encodeWithCoder: for the objects in question to make them serialize properly.

Related

Access raw NSData for a Transformable attribute in Core Data

In my model, I have an attribute transformingString that stores an NSString object as NSData, using the "Transformable" type. In my code, I have an NSString as an dynamic property in my NSManagedObject, and accessing that property automatically invokes the value transformer to convert from NSData to NSString.
In some cases, though, I want to access the raw NSData in my code, without invoking the NSValueTransformer, so I can handle the NSData in a different way for some edge case. How can I do this? I don't think there is any way to just turn off the Transformable type for my Core Data model. I'm hoping there is some way to access the raw NSData directly that is passed into the transformer.
I've tried [self primitiveValueForKey: #"transformingString"] but that also invoked the NSValueTransformer and returns the NSString type. Is there a way to do this?
If i resume you want access a value on a NSManagedObject that is not stored in persistent Store. I suggest you to add a category on your NSManagedObject. In this category declare a property in readonly (for be sure that not use for an other thing). In the implementation return the raw NSData.

How to call encodeWithCoder

Possibly a nooby question - how is encodeWithCoder called? I need to use this to save objects in files on the iphone, I am just unsure of how it is actually called. Do I have to manually call it? If so, what do I use as input for the NScoder argument?
You don’t call it yourself, you use NSKeyedArchiver instead:
NSData *serialized = [NSKeyedArchiver archivedDataWithRootObject:foo];
Where foo is your object that conforms to NSCoding. There’s also a method to save the archived object directly to a file.

Populating a UITableView with Arrays of strings

I'm trying to create a save & load module in my app. So the user can save some specific info and then load it at any point in time.
What I'm saving is an array of NSMutableStrings. I'm creating an iPad app so the saved info will be presented in a popover with a TableView.
So, here's the question. I would like to populate that tableView with my saved arrays, and for that I need to store my arrays somewhere. I'm new to objective-c and programming in general, and would like your advice on what's the best way of doing that.
Should I use a plist to store those arrays with Keys, so the keys will be the names that the user introduces when saving and also the name of the tableView cells? or maybe a simple NSMutableDictionary will do?
Please advise.
This answer might help you. Using Core Data might be overkill here, and saving to a plist is extremely easy. This is Benoît's answer from the linked question:
NSString *error;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"yourFile.plist"];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:rootObj
format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
if(plistData) {
[plistData writeToFile:plistPath atomically:YES];
}
else {
NSLog(#"Error : %#",error);
[error release];
}
where rootObj is the object you wish to serialize, in this case, your array/dictionary.
Also, if you are going to be read/writing to this data frequently during the course of your app, using a singleton which can make a huge difference performance-wise instead of constantly reading/writing from/to a file. You can load all of your data into the singleton on app-launch and save it upon applicationWillTerminate.
To answer your array/dictionary question, it depends on how you are obtaining your strings and how you want them to be ordered. Sorting an array is extremely easy, as you can see in this answer.
Sergey, based on your description, I would advise you look into using Core Data for data storage.
https://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coredata/cdprogrammingguide.html
In addition to storing data, Apple has extended the use of Core Data in all sorts of neat ways, including the use of stored data to populate a UITableViewController through the use of NSFetchedResultsController
https://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html
That's it, give that a read and you should be well on your way.

Which method is better to save data nsdictionary or plist?

I want to save data locally but i do not know which method is better nsdictionary or plist?Can anyone tell which method is better and why?
Thanks in advance!
I think maybe what you meant to ask is which is better, plist or binary. If you save an NSDictionary to file using writeToFile: it will be stored as a plist. So in that sense there is zero difference between the two.
However, you also have the option of converting an NSDictionary instance into a serialized NSData representation, and then storing the serialized data as a binary file.
As for which is better and why, that depends upon what you want to do. The API for converting an NSDictionary to/from a plist file is more convenient to use than the API for serializing and reconstructing to/from NSData. However, storing an NSDictionary as a plist file only works if everything in the dictionary is a plist object (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) and if all of your keys are of type NSString. Otherwise your writeToFile: call will fail with frustratingly little information being provided about why.
So if your data structure meets the requirements for being stored as a plist and you cannot foresee it ever being changed such that it would no longer meet the requirements then you may find it more convenient storing it as a plist. Otherwise your only option is to do a binary serialization and storage using NSData. You may prefer this latter option if you want to have code that cannot be accidentally broken by someone sticking a non-plist-object in your data structure.

NSUserDefaultsProblem

I have a simple problem:
I add an object to an NSArray, then I add an object to it then I use the NSUserDefaults way to save the array, but it doesn't work, I mean the array isn't saved and the console sends me this messange:
2011-03-21 23:09:53.994 Project[10490:207] * -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '(
""
)' of class '__NSArrayM'.
does anybody know how can I fix this.
NSUserDefaults only allows you to save basic lightweight objects; for example NSString, NSNumber and NSData. If you want to add another class, you'll have to shoehorn it into an NSData object beforehand. This is pretty simple, usually just a call to [NSKeyedArchiver archivedDataWithRootObject:array];. Note that the objects in the array must implement the NSCoding protocol, which you'll have to add to any of your own custom classes if that's what you want to save.
Also keep in mind NSUserDefaults is meant for lightweight preferences, not application data. If you have a large array of objects, you might be better served by archiving it to its own file or using Core Data (if you feel comfortable using something a little more advanced).
The only types you can save in NSUserDefaults are property list types: NSString, NSDate, NSArray, NSDictionary, NSNumber, NSData. You're probably trying to save an array of objects that aren't one of these types.