Reputation: 125
I have an entity in which i have some attributes to which I have pass custom class which store data in an array of that class My core data entity looks like this,
My NSManangedObject
Class looks like this,
extension SingleChat {
@nonobjc public class func fetchRequest() -> NSFetchRequest<SingleChat> {
return NSFetchRequest<SingleChat>(entityName: "SingleChat")
}
@NSManaged public var name: String?
@NSManaged public var roomSID: String?
@NSManaged public var isGroup: Bool
@NSManaged public var lastMessage: String?
@NSManaged public var lastMsgTime: String?
@NSManaged public var lastMsgTimeActual: String?
@NSManaged public var profilePic: String?
@NSManaged public var lastMsgRead: Bool
@NSManaged public var unReadMsgsCount: Int16
@NSManaged public var actualNameFor_1_2_1_chat: String?
@NSManaged public var isNewGroup: Bool
@NSManaged public var members : [TCHMember]
@NSManaged public var messages : [TCHMessage]
@NSManaged public var twChannelObj: TCHChannel?
@NSManaged public var groupInfo : [String:JSON]?
}
This is how i save my data in core data ,
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let context = appDelegate?.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "SingleChat", in: context!)
let user = NSManagedObject(entity: entity!, insertInto: context)
for items in dateWiseSortedSingleRooms
{
user.setValue(items.name, forKey: "name")
user.setValue(items.actualNameFor_1_2_1_chat, forKey: "actualNameFor_1_2_1_chat")
user.setValue(items.isGroup, forKey: "isGroup")
user.setValue(items.lastMsgRead, forKey: "lastMsgRead")
user.setValue(items.lastMsgTimeActual, forKey: "lastMsgTimeActual")
user.setValue(items.lastMessage, forKey: "lastMessage")
user.setValue(items.lastMsgTime, forKey: "lastMsgTime")
user.setValue(items.profilePic, forKey: "profilePic")
user.setValue(items.roomSID, forKey: "roomSID")
user.setValue(items.isNewGroup, forKey: "isNewGroup")
user.setValue(items.unReadMsgsCount, forKey: "unReadMsgsCount")
user.setValue(items.unReadMsgsCount, forKey: "unReadMsgsCount")
user.setValue(items.members, forKey: "members")
user.setValue(items.messages, forKey: "messages")
user.setValue(items.twChannelObj, forKey: "twChannelObj")
}
do {
try context?.save()
print("Saved successfully.")
} catch {
print("Fail to save")
}
Now when my code execute app crashes at this line,
user.setValue(items.members, forKey: "members")
user.setValue(items.messages, forKey: "messages")
With error this,
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TCHMember encodeWithCoder:]: unrecognized selector sent to instance 0x2807a1780
How I can resolve this? and store my custom class array data in it?
Upvotes: 2
Views: 1779
Reputation: 15257
If you want to store non-standard objects in core data, the corresponding attribute is of type transformable
, so that it can be converted to NSData
and back.
This can be done if the object adopts the NSCoding protocol, which requires to implement the functions encode(with:)
and init(coder:)
(described there). These functions define which properties of your custom object have to be stored and restored.
An example how to use these functions can be found here.
EDIT:
There is another way to handle transformable attributes: Instead of adopting the NSCoding
protocol, you could implement your custom NSValueTransformer
. This class can be implemented independently of your 3rd party classes, see here, and is specified in your core data model, see here. An example can be found here.
EDIT 2:
I did not use the 2nd method by myself, but my impression is:
In oder to store a custom object in core data, it must be converted to NSData
, and during a fetch NSData
must be converted back to your object.
One way to do so is to use NSCoding
, but this requires to implement it in the custom class, maybe as an extension. If this is not possible, as in your case, you can implement a custom NSValueTransformer
object.
For encoding, it is given one of your custom objects as input, and creates as appropriate an NSData
object from the relevant properties. For decoding, it accepts a NSData
object, and initialises a new instance of your custom object, and sets these properties.
You just have to specify the name of the NSValueTransformer
in your core data model, and core data will use this custom NSValueTransformer
. You can find an example here.
Upvotes: 2