Looking into Realm.io and trying to figure out of how to store customer types like CMTime, CMTimeRange, I'm using to store them in NSData in CoreData based on these ideas;
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html#//apple_ref/doc/uid/TP40001919-SW1
I would like just before the object gets saved, to store all the customer types in an NSData blob.
Realm does not currently have an equivalent to awakeFromFetch or willSave, but you can approximate that functionality by using computed (unpersisted) properties.
Related
I've having difficulty saving an NSManagedObject in userDefaults and I'd like to know a) should I be trying to do this or is this not an appropriate approach or b) if it is an appropriate approach, how can I get it to work?
I'm writing my app in Swift 2.3 and it has a few user default options, one of which is for a default "lift" (as in weightlifting, e.g. 'bench press', 'clean and jerk', 'incline bench press'). I'm actually converting them from an enum to a Core Data entity because every lift event that the user will be able to keep track of will be one of the available lifts types (for which I'll establish the appropriate relationship).
Here's the extension with the properties:
extension Lift {
#NSManaged var liftName: String
#NSManaged var type: NSSet
}
and the Lift entity with the things Xcode is complaining about:
class Lift: NSManagedObject, NSCoding {
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(liftName, forKey: "liftName")
} // Super.init isn't called on all paths before returning from initializer
required init(coder aDecoder: NSCoder) {
// Initialization of immutable variable was never used, etc...
let liftName = aDecoder.decodeObjectForKey("liftName") as! String
}
}
I've dealt with these types of errors before so my real concern is whether or not I'm headed down the wrong path.
I've read numerous threads tonight which have taught me that I'll need to encode an object (but not specifically an NSManagedObject) to save it then unencoded it when retrieving it and that my class must conform to NSCoding and what that protocol requires. But then I've seen threads that say NSManagedObjects should NOT be stored in userDefaults, but I don't know if that's true.
I've spent a few hours on this so before I go further, can/should this be done?
No, you should not store an NSManagedObject in NSUserDefaults. Core Data is an object persistence technology, so it doesn't make sense to try and persist an NSManagedObject in some other format.
There are few alternatives you can use:
You could simply store the name of the lift in your user defaults and then query for this to get the object back from Core Data. This may not work for you if lift names aren't unique
You can add an identifier attribute to your Lift entity and store something like a UUID string in that attribute; You can then store the same string in UserDefaults. This will ensure one object is selected uniquely.
You can add a new boolean attribute to your Lift entity default and again use a query to retrieve it; You would need to ensure you only set the value to true on one lift at a time.
You can use managedObject.objectId.uriRepresentation to get a URL that you can store as a string and then use to retrieve the object later. This is probably the most complex solution and I would suggest you try one of the other options.
No, You cannot do this. You cannot save Core Data objects in User Defaults. It can only save in its DB.
This two are totally two different things. NSUserDefault stores the light pieces of data where NSManagedObject stores the light or heavy amount of data and is very fast than NSUserDefault for storing and retrieving purposes.
NSManagedObject -> NSManagedObject link to coredata.
You should it to store a large list of elements. As far your last question, there is nothing preventing you from using both Core Data and a backend to store your data. In fact, there are frameworks out there to facilitate exactly this.
NSUserDefaults -> NSUserDefaults is a class that allows simple storage of different data types. It is ideal for small bits of information you need to persist between app launches or device restarts. NSUserDefaults is not sufficient and reliable to store and query the huge amount of data. It's suggestable if you'll have a backend (database on the server) to store events and their invitees to persist consistency of user's information (if user logged in back to your app from other app supportive device then he'll get all information he stored).
NSUserDefaults supports the following data types:
NSString, NSNumber, NSDate, NSArray, NSDictionary and NSData
Hope it will help you.
Storable Types in NSUserDefaults.
The NSUserDefaults class acts very much like something called a Property List (aka plist). It may be just a fancy interface for a plist, or it may be more, I’m not entirely sure. Nonetheless, plists are limited in what kind of objects they can store. The six types plists can store are:
NSData
NSString
NSNumber
NSDate
NSArray
NSDictionary
So,you need to use in NSKeyedArchiver.
let ArchvieArr = NSMutableArray()
ArchvieArr.addObject(NSKeyedArchiver.archivedDataWithRootObject(LiftObj)).
NSUserDefaults.standardUserDefaults().setObject(ArchvieArr, forKey: "savedArray")
Given a group of core data entities (let's call them phrases), what is the best/most correct way of having one phrase as "the active phrase" and enforcing only one active phrase at a given time.
I thought about having a Bool value on the phrase entity, but I don't know how to enforce true to only be on one entity out of the set. I guess I could also have another entity (activePhrase) which stores just one record in it but again I'm not sure how to enforce the 'select one of many phrases to be active' requirement.
I fear this may be a dumb question - my CoreData (and indeed database) knowledge is a bit rusty and I want to make sure I'm following best steps.
I'd get the active object's object ID and save that in user defaults.
You'd get something you can save by:
Asking the managed object for its objectID
Asking the object ID for its URIRepresentation (an NSURL)
Converting the NSURL to NSData by using NSKeyedArchiver's archivedDataWithRootObject method.
Then save that to user defaults. To reverse the process,
Read the NSData object from user defaults
Convert that back to an NSURL by using NSKeyedUnarchiver's unarchiveObjectWithData method
Convert the NSURL back to an NSManagedObjectID by using NSPersistentStoreCoordinator's managedObjectIDForURIRepresentation method.
Get the actual managed object by using NSManagedObjectContext's existingObjectWithID method.
Basically, i want to save my current Parse user's friends into NSUserDefaults. For some reason it doesn't seem to be saving correctly or it won't let me save them. Is this because the array of objects(friends) that i am returning is to intricate for NSUserDefaults to handle?
I have tried turning the array of objects into NSData and saving it that way but i still haven't yielded any good results.
I would really appreciate if someone could help me out.
Cheers.
You really should not use NSUserDefaults for storing this type of information. NSUserDefaults was created in order to store and retrieve "settings" type information as opposed to data.
As for your question, in order to save custom objects you need to implement these 2 methods:
- (void)encodeWithCoder:(NSCoder *)encoder {
}
- (id)initWithCoder:(NSCoder *)decoder {
}
These methods will essentially tell the application how to store the objects data in a file as well as how to read it back in and create an object from it.
Documentation:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html
However, if you are looking to store these objects locally you should look into Parse's local caching feature. You could also use Core Data to store the objects locally but maintaining 2 instances of the objects may be ugly.
Parse Local Caching:
https://www.parse.com/docs/ios_guide#localdatastore/iOS
In my app I will have an array of up to 50 images that people can maintain. They can choose to create new or delete existing images. Each image will have a few things associated with them, like a rating for example.
My question is how I should go about storing them. Should I create a CoreData entity called "Image" and store them that way? Should I set up a UIView subclass that conforms to NSCoding and just encode and decode the array and store it on the device? Is there another way I should consider? Thanks for any suggestions.
You can create an entity that represents the image with its information, and use core data's external storage property for entity's attribute. This way, you get the convenience of core data without actually storing the images on the persistent store.
I had to make a similar decision recently and I decided to store the image in CoreData. I have a managed object called photo with a Binary Data field called image:
photo.image = UIImagePNGRepresentation(imageFile); // <- imageFile is a UIImage
And I recreate the image using:
[UIImage imageWithData:self.image];
One immediate advantage is that the images are deleted automatically with the object and there's no extra overhead in retrieving the image if you've already queried for the record.
Core Data is probably overkill for what you want to do. Choose some key value pairs for descriptive information about the image. One key will be "path" and the value will be the path to the image file (or just its name). You can serialize array (or set) of dictionaries.
When your app starts up, read in the serialized array of dictionaries. Every time something changes, serialize and save the information. Write a short audit routine to insure that there is a one - to - one correspondence between dictionaries and images on file, and if one or the other is missing delete the other (will handle situations were you crash before getting to update something or the other).
Later on you can add more attributes to the dictionaries if you want, or even remove some.
[PS: I did this in a shipping app for one version, when the information needed to become relational I switched to Core Data.]
I am working on an application where the user is able to draw on the screen with their finger. I am using UIBezierPath for this. I need to persist this data which is an NSArray containing multiple BezierPath objects. What is the best way to go about this? Store in coredata, store in a file using NSData? Much obliged.
Are you expecting to have to store multiple objects? Will you need to be able to fetch them based on some filter or ordering? I recommend using Core Data to save yourself a decent amount of work in packing/unpacking the data. There isn't really a reason to store it in a file.
edit:
As the other answer said, you just archive it to NSData. The UIBezierPath class adheres to the NSCoding protocol so you can do something like this to archive it:
NSData *bezierData = [NSKeyedArchiver archivedDataWithRootObject:bezierPath];
You can persist that NSData object in Core Data.
To decode the archive, assuming we have a bezierData NSData object, you can do something like:
UIBezierPath *bezierPath = [NSKeyedUnarchiver unarchiveObjectWithData:bezierData];
Archive the UIBezierPath to NSData, and store it as an attribute of type NSData in CoreData. You can have an easier API if you make it a transformable attribute.
It's pretty easy to do, especially for classes that already support archiving.
See this document for more information.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html