2

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,

enter image description here

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?

7
  • If you recently added new property to your core data structure you need to reinstall the app once. Commented Feb 18, 2019 at 12:08
  • No i haven't added new property it is showing me error while saving this line of code, user.setValue(items.members, forKey: "members"). @DharmeshKheni Commented Feb 18, 2019 at 12:17
  • This may help: stackoverflow.com/questions/45211115/… Commented Feb 18, 2019 at 12:30
  • My TCHMember AND TCHMessage class is basically twilio classes with base class of NSObject, now how i can set there encoder? @DharmeshKheni Commented Feb 18, 2019 at 13:01
  • May be you can add encoder to their class? Commented Feb 18, 2019 at 13:13

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for this concise answer, i have one question related to my criteria, i'm converting my attribute "members" to Transformable and passes the the array of [TCHMember] to its custom class. Now TCHMember is a class of third party library twilio. How can i encode it first it and than store data in it? As you can see in above question i'm saving data in that attribute. @Reinhard Männer
Oh, I am sorry, I was not aware that these classes are third party (I regarded twilio as a typo of two). Maybe it is possible to write an extension to these classes in which both functions are declared?
This TCHMember is declared as interface TCHMember : NSObject in TCHMember class of twilio and same TCHMessage. @Reinhard Männer
I'm passing NSCoder with class of NSManagedObject like this, @objc(SingleChat) public class SingleChat: NSManagedObject,NSCoder { I'm getting an error Multiple inheritance from classes 'NSManagedObject' and 'NSCoder'. Why is this so? @Reinhard Männer
@Junaid Khan Did you read my edit? I think this should solve your problem.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.