CoreData common practice - Do you usually have a struct based data class, as the bridge between your UI layer, and the CoreData data layer?

I was wondering, when you use CoreData, do you usually create another equivalent struct based data class, to compliment the NSManagedObject?

The struct based data class, will act as the bridge, between UI layer, and CoreData data layer.

For instance, I have the following CoreData model data class.

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

extension NSTabInfo {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<NSTabInfo> {
        return NSFetchRequest<NSTabInfo>(entityName: "NSTabInfo")
    }

    @NSManaged public var colorIndex: Int32
    @NSManaged public var customColor: Int32
    @NSManaged public var name: String?
    @NSManaged public var order: Int64
    @NSManaged public var typeValue: Int32
    @NSManaged public var syncedTimestamp: Int64
    @NSManaged public var uuid: UUID

}

extension NSTabInfo : Identifiable {

}

We need a UI, to represent such model data object. Initially, we have the following UI class

class TabInfoCell: UICollectionViewCell {
    private var tabInfo: NSTabInfo?

    func update(_ tabInfo: NSTabInfo) {
        self.tabInfo = tabInfo
    }
}

But, we just feel not comfortable with such design.

  • Letting TabInfoCell (UI class) to hold NSTabInfo (CoreData model data class) doesn't feel right, as NSTabInfo contains CoreData's context. I do not feel comfortable, to expose CoreData's context to an UI.
  • Will holding a class reference to NSTabInfo in UI, affect CoreData memory allocation/ deallocation strategy? Using weak reference might solve the issue. But, what should the UI do when the weak reference become nil?

With such concern, We have the following design

struct TabInfo {
    enum Kind: Int {
        case All = 0
        case Calendar
        case Custom
        case Settings
    }
    
    let kind: Kind
    var name: String?
    var colorIndex: Int
    var customColor: Int
    var order: Int
    var syncedTimestamp: Int64
    var uuid: UUID
}

@objc(NSTabInfo)
public class NSTabInfo: NSManagedObject {
    convenience init(context: NSManagedObjectContext, tabInfo: TabInfo) {
        self.init(context: context)
        
        self.colorIndex = Int32(tabInfo.colorIndex)
        self.customColor = Int32(tabInfo.customColor)
        self.name = tabInfo.name
        self.order = Int64(tabInfo.order)
        self.typeValue = Int32(tabInfo.kind.rawValue)
        self.syncedTimestamp = tabInfo.syncedTimestamp
        self.uuid = tabInfo.uuid
    }
    
    func toTabInfo() -> TabInfo {
        return TabInfo(
            kind: TabInfo.Kind(rawValue: Int(self.typeValue))!,
            name: self.name,
            colorIndex: Int(self.colorIndex),
            customColor: Int(self.customColor),
            order: Int(self.order),
            syncedTimestamp: self.syncedTimestamp,
            uuid: uuid
        )
    }
}

@nonobjc public class func fetchRequest() -> NSFetchRequest<NSTabInfo> {
        return NSFetchRequest<NSTabInfo>(entityName: "NSTabInfo")
    }

    @NSManaged public var colorIndex: Int32
    @NSManaged public var customColor: Int32
    @NSManaged public var name: String?
    @NSManaged public var order: Int64
    @NSManaged public var typeValue: Int32
    @NSManaged public var syncedTimestamp: Int64
    @NSManaged public var uuid: UUID

}

extension NSTabInfo : Identifiable {

}

Then, in our UI class, it looks like

class TabInfoCell: UICollectionViewCell {
    private var tabInfo: TabInfo?

    func update(_ tabInfo: TabInfo) {
        self.tabInfo = tabInfo
    }
}

I was wondering, does such design philosophy make sense? Do you usually have a struct based data class, as the bridge between your UI layer, and the CoreData data layer?

Thanks.

CoreData common practice - Do you usually have a struct based data class, as the bridge between your UI layer, and the CoreData data layer?
 
 
Q