Search code examples
swiftcore-data

Passing entity of core data model as function parameter, error


I have Model named: Year, In this model I have entity named: Spring, Summer, Autumn and Winter.

The function is:

    func saveToDisk<T: NSManagedObject>(of entityName: T.Type, with context: NSManagedObjectContext, and dictionary: Dictionary<String, Any>)
        {
         let season= entityName.init(context: context)
        

                  if let iconName = dictionary["iconName"] as? String
                    {
                       season.iconName = iconName
                    }
}   

In above code I receive error: value of type 'T' has no member 'iconName'

Code to call function:

for jsonDictionary in jsonArray
     {
                        
     switch monthCount
         {
            case 1…2:
                    saveToDisk(of: Winter, with: coreDataStack.managedContext, and:  jsonDictionary)
            case 3…5:
                    saveToDisk(of: Spring, with: coreDataStack.managedContext, and: jsonDictionary)
            case 6…8:
                    saveToDisk(of: Summer, with: coreDataStack.managedContext, and: jsonDictionary)
            ....

         }
      }

Here's the class derived from Editor> CreateNSManaged Subclass from Model entity.

@objc(Winter)
public class Winter: NSManagedObject {
}    
    

extension Winter {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Winter> {
        return NSFetchRequest<Winter>(entityName: “Winter”)
    }

    @NSManaged public var date: Date?
    @NSManaged public var iconName: String?
    @NSManaged public var id: UUID?

}

Solution

  • The generic type T in saveToDisk doesn't provide the properties of the NSManagedObject subclass at compile time which is necessary to access iconName.

    There are two solutions:

    1. Use KVC (Key-Value Coding)

      if let iconName = dictionary["iconName"] as? String {
          season.setValue(iconName, forKey: "iconName")
      }
      
    2. Create a protocol

      protocol Season {
          var iconName: String? {get set}
      }
      
      class Winter: NSManagedObject, Season {}
      

      and

      func saveToDisk<T: NSManagedObject>(of entityName: T.Type, 
                                           with context: NSManagedObjectContext, 
                                         and dictionary: Dictionary<String, Any>) where T : Season