Saving custom class into Coredata - ios

Hi i have used attribute type transformable and i have followed the procedure of archiving in one of the Forum .
But it says
CoreData: warning: no NSValueTransformer with class name 'SurveyResults' was found for attribute 'survey' on entity 'SurveyData'
2013-04-30 09:44:16.022 TestReachability[11641:c07] -[SurveyApplication encodeWithCoder:]: unrecognized selector sent to instance 0x845cb00
2013-04-30 09:44:16.023 TestReachability[11641:c07] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SurveyApplication encodeWithCoder:]: unrecognized selector sent to instance 0x845cb00'
Here is my code
SurveyApplication *survey =[[SurveyApplication alloc]init];
survey.name=#"dheeraj";
survey.phone=#"573-356-2598";
NSManagedObject *aStory = [NSEntityDescription insertNewObjectForEntityForName:#"SurveyData"inManagedObjectContext:self.managedObjectContext];
[aStory setValue:survey forKey:#"survey"];
NSError *saveError = [[NSError alloc]init];
if (![self.managedObjectContext save:&saveError]) {
NSLog(#"%#",saveError);
}
SurveyAppplication object is my custom class and im trying to create an object and then store it core data .Could you please help me out.
Thanks
Dheeraj

It's not enough to make the attribute transformable, you also need to arrange for the transformation to happen. You can't just tell Core Data to transform any old object and expect it to know what to do. You have a couple of options:
Don't tell Core Data how to transform the data. In this case, Core Data will attempt to call encodeWithCoder: on your object to convert it to NSData. That's why you get the error that mentions this method-- it's trying to call the method on your class, but that method doesn't exist. In this case your class must conform to NSCoding for the transformation to occur.
Tell Core Data how to transform the data. In this case you create a subclass of NSValueTransformer that performs the transformation. You configure this on the attribute, either in the Core Data model editor or in code. In this case, you must have a custom transformer class that knows how to perform the transformation.

Related

App crashes when saving a dictionary object in Firestore

I was trying to save my quiz data into firestore like so
db.collection("Quizzes").addDocument(data: ["Author": userEmail,
"quizTitle": quizTitle,
"quizDescription": quizDescription,
"quizDictionary": quizDictionary]) { (error) in
if let e = error{
print("There was an erorr saving the data to the Firestore \(e)")
}
after clicking the button that would perform this block of code my app crashes and the following error is printed
020-09-19 17:17:46.367783+0800 Quizzler[18001:782362] -[__NSCFNumber length]: unrecognized selector sent to instance 0xc4cd28a1a98b5156
2020-09-19 17:17:46.469546+0800 Quizzler[18001:782362] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0xc4cd28a1a98b5156'
After doing some debugging, I found out that the "quizDictionary": quizDictionary part is what's causing the crash. Why is this happening? I thought that the method .addDocument(data: ) accepts [String: Any]?
If it is impossible to save Dictionary object into firestore, what are some workarounds for this?
If needed, this is my dictionary's declaration
dictionary declaration
Hey have a look here at the documentation for adding and managing data in fireStore :- https://cloud.google.com/firestore/docs/manage-data/add-data#swift.
Quick Overview line :- Using Map or Dictionary objects to represent your documents is often not very convenient, so Firestore supports writing documents with custom classes. Firestore converts the objects to supported data types.
Update :- As mentioned in comments it does not just convert any random object into a supported type. If you throw an NSImage at it, it won't know what to do with that. Or if the object contains some other random object it won't work. It has to contain supported types only. You can refer to this link to understand more about the supported data types.
You can only read and write supported data types with Firestore:
arrays
booleans
bytes
Firestore date objects
floating-point numbers
Firestore geographical objects
integers
maps (dictionaries, with string keys and values only of these supported types)
nil
Firestore references
strings
Therefore, you must convert your custom object to a format that is recognizable to Firestore which means replacing custom types with types that are primitive to the database.
https://firebase.google.com/docs/firestore/manage-data/data-types

Inverse Relationship with Core Data Causes Crash when Adding Object to NSSet

I have 2 entities in Core Data, a Bill and Person. I have two relationships:
Bill to Person is a 'To Many' relationship called 'people'
The inverse - from Person to Bill is 'To One'- called 'bill'.
The result generated by Xcode (along with the classes) are:
Bill:
extension Bill {
#NSManaged var people: NSSet?
}
Person:
extension Person {
#NSManaged var bill: Bill?
}
This is the method I've written to add a Person object to the Bill's NSSet:
class Bill : NSManagedObject {
...
func addPersonToBill(contact : CNContact){
let entDesc = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext())
// Create Person object with custom initialiser
let person = Person(contact: contact, entity: entDesc!, insertIntoManagedObjectContext: managedObjectContext())
print("Got person")
people = people?.setByAddingObject(person) // CRASHES HERE
}
}
The custom initialiser for Person is:
init(contact : CNContact, entity : NSEntityDescription, insertIntoManagedObjectContext context : NSManagedObjectContext?){
super.init(entity: entity, insertIntoManagedObjectContext: context)
// I set other properties here using info from the CNContact
}
However, when I add a Person, it crashes at people?.setByAddingObject(person) with the error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_TtCs21_SwiftDeferredNSArray
isEqualToSet:]: unrecognized selector sent to instance 0x7fc7ed875cb0'
When I delete the bill relationship from Person to Bill, it runs fine and the Person is added to the Bill's 'people' NSSet. I could leave it like this as I don't necessarily need this inverse relationship, but I've read that it is best to have an inverse relationship unless I have a good reason not to. I also face this issue with other relationships in my app, so I would have a lot of relationships without their inverse.
Any ideas what's wrong? Are my relationships incorrect? One Bill can have many Persons, but one Person can only have one Bill.
The solutions I've tried are:
Adding this accessor from this answer:
#NSManaged func addPeopleObject(value:Person)
But I get the error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[NSSet intersectsSet:]:
set argument is not an NSSet'
Creating an NSMutableOrderedSet as suggested by other answers:
let mutPeople = NSMutableOrderedSet(array: (people?.allObjects)!)
mutOwers.addObject(person)
people = NSSet(array:mutPeople.array)
...but I get the same, original crash message.
Unwrapping 'people' - still get the same crash message.
Any help would be much appreciated, thanks.
Ah, I had a similar problem as [this question].1 I had a method on Bill called getOwers which had a return type of an array, and this seemed to override the accessor CoreData creates. I changed the method to getOwersArr, and all is fine now. Thanks to #Paulw11 for pointing me in the right direction!
I also have to-many relationships implemented as NSSet. I add/delete objects to the set (without any problems) using code like the following:
let mutableSet = bill.mutableSetValueForKey("people")
mutableSet.addObject(newPerson)
// (next, save managed object context)
I had a similar issue with iOS 9.3 in a one-to-many relationship.
I fixed it by replacing:
group.addToTeams(team) // Crashes on iOS 9.3
with:
team.group = group // This will correctly add team to the set without crashing
Basically instead of adding and object to the set use the Inverse relationship.

What type of object is returned from ObjectForID

I am trying to retrieve an object from the managed object context and edit a value or two after it has been backed up to the cloud. In particular, I want to save an id provided by the cloud server.
To get the object, I'm trying to retrieve it using its managedObjectID.
I have tried:
Contacts *object = [_managedObjectContext objectWithID:_moID];
and
Contacts *object = [self.managedObjectContext objectRegisteredForID:_moID];
where moID is the managedObject id.
I then follow this up with
object.cid = #99; //ie I set it equal to some number
In both cases, although Contacts is an NSManagedObject class, it throws a yellow warning:
'Incompatible point types initializing contacts with an expression of type NSManagedObject'.
If Instead of calling it Contacts *object, I call it NSManagedObject *object, it no longer throws the warning but then will not allow me to say object.cid as it no longer knows what a cid is. In this case it throws red error:
Property cid not found on object of type NSManagedObject.
Can anyone suggest proper object type. Thanks in advance for any suggestions.
By looking at the method definition, you'll see that returned instance type is just NSManagedObject * as the warning said. What you need to do is just to cast the type appropriately:
Contacts *object = (Contacts *)[_managedObjectContext objectWithID:_moID];
and
Contacts *object = (Contacts *)[self.managedObjectContext objectRegisteredForID:_moID];
Note, your Contacts suppose to be a subclass of NSManagedObject.

Creating one -> many relationships for a shopping list application swift 2

I have the following relationship
The idea is that one "List" entity will have access to many "ItemList" entities i.e. a list will have multiple items on it. I have attempted to add an item to a list entity in the following way:
let newList = NSEntityDescription.insertNewObjectForEntityForName("List", inManagedObjectContext: context) as! List
newList.name = listName
newList.shoppingDate = shoppingTripDate
newList.eventDate = eventDate
let itemEnt = NSEntityDescription.insertNewObjectForEntityForName("ItemList", inManagedObjectContext: context) as! ItemList
itemEnt.item = "Eggs"
itemEnt.list = newList
With the line ItemEnt.list = newList connecting the two, as you can see with the above screenshot.
However, in another view controller where I retrieve this object from core data and try to access its item property like so:
shoppingListObject!.itemList!.item
This crashes the program.
Am I missing anything or doing something wrong?
edit:
This is the error it produces in the terminal
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSFaultingMutableSet item]: unrecognized selector sent to instance 0x7fd0a4951960'
That error is telling you that itemList is an NSSet. Which makes sense, since that's how Core Data's to-many relationships work. It's also telling you that NSSet doesn't have a method named item, which also makes sense. You tried to call a method on an NSSet that NSSet doesn't have, which is why the app crashed.
From your model diagram, shoppingListObject!.itemList! is an NSSet of instances of ItemList. You can access individual instances using NSSet methods.
But I agree with Martin's comment-- it's strange that you're able to compile this code. Swift should catch that, unless you're doing something unusual that prevents it from doing so.

CoreData entity's are not being correctly initialised

im having a hard time with what it seems a very simple task. Im trying to create an entity (LVUser) and calling a custom method implemented in the class previously mentioned. Every attempt i made returns me an unrecognised selector sent to instance error. Im using MagicalRecord in my project but also tried with CoreData raw methods without luck anyway.
First Attempt
LVUser* user = [LVUser MR_createEntity];
[user signInWithDelegete:self];
Second Attempt
LVUser* user = [LVUser MR_createInContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext];
[user signInWithDelegete:self];
Third Attempt
LVUser* user = [[NSManagedObject alloc] initWithEntity: [LVUser MR_entityDescription] insertIntoManagedObjectContext:[RKObjectManager sharedManager].managedObjectStore.mainQueueManagedObjectContext];
[user signInWithDelegete:self];
The last example gives me this warning
Incompatible pointer types initializing 'LVUser *' with an expression of type 'NSManagedObject *'
I don't get what i'm doing wrong, they are compatible pointer types indeed.
I tried deleting Xcode Derived Data and clean & build.

Resources