Use manual codegen for CoreData models

This commit is contained in:
Shadowfacts 2022-01-09 17:21:27 -05:00
parent 2b38b883fe
commit eded49b266
11 changed files with 237 additions and 80 deletions

View File

@ -16,7 +16,6 @@
D65B18BE275051A1004A9448 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18BD275051A1004A9448 /* LocalData.swift */; };
D65B18C127505348004A9448 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18C027505348004A9448 /* HomeViewController.swift */; };
D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */; };
D6A8A33727766EA100CCEC72 /* ManagedObjectExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */; };
D6C687EC272CD27600874C10 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C687EB272CD27600874C10 /* AppDelegate.swift */; };
D6C687EE272CD27600874C10 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C687ED272CD27600874C10 /* SceneDelegate.swift */; };
D6C687F6272CD27600874C10 /* Reader.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */; };
@ -34,8 +33,13 @@
D6C68856272CD7C600874C10 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C68855272CD7C600874C10 /* Item.swift */; };
D6C68858272CD8CD00874C10 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C68857272CD8CD00874C10 /* Group.swift */; };
D6E2434C278B456A0005E546 /* ItemsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2434B278B456A0005E546 /* ItemsViewController.swift */; };
D6E24350278B62F60005E546 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2434F278B62F60005E546 /* Item.swift */; };
D6E24352278B6DF90005E546 /* ItemsSyncUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24351278B6DF90005E546 /* ItemsSyncUpdate.swift */; };
D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */; };
D6E24358278B96E40005E546 /* Feed+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */; };
D6E2435D278B97240005E546 /* Item+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24359278B97240005E546 /* Item+CoreDataClass.swift */; };
D6E2435E278B97240005E546 /* Item+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */; };
D6E2435F278B97240005E546 /* Group+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */; };
D6E24360278B97240005E546 /* Group+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -86,7 +90,6 @@
D65B18BD275051A1004A9448 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
D65B18C027505348004A9448 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = "<group>"; };
D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistentContainer.swift; sourceTree = "<group>"; };
D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedObjectExtensions.swift; sourceTree = "<group>"; };
D6C687E8272CD27600874C10 /* Reader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Reader.app; sourceTree = BUILT_PRODUCTS_DIR; };
D6C687EB272CD27600874C10 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D6C687ED272CD27600874C10 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -107,8 +110,13 @@
D6C68855272CD7C600874C10 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
D6C68857272CD8CD00874C10 /* Group.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = "<group>"; };
D6E2434B278B456A0005E546 /* ItemsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsViewController.swift; sourceTree = "<group>"; };
D6E2434F278B62F60005E546 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
D6E24351278B6DF90005E546 /* ItemsSyncUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsSyncUpdate.swift; sourceTree = "<group>"; };
D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+CoreDataClass.swift"; sourceTree = "<group>"; };
D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+CoreDataProperties.swift"; sourceTree = "<group>"; };
D6E24359278B97240005E546 /* Item+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataClass.swift"; sourceTree = "<group>"; };
D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataProperties.swift"; sourceTree = "<group>"; };
D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Group+CoreDataClass.swift"; sourceTree = "<group>"; };
D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Group+CoreDataProperties.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -173,8 +181,14 @@
D6A8A33527766E9300CCEC72 /* CoreData */ = {
isa = PBXGroup;
children = (
D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */,
D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */,
D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */,
D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */,
D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */,
D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */,
D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */,
D6E24359278B97240005E546 /* Item+CoreDataClass.swift */,
D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */,
);
path = CoreData;
sourceTree = "<group>";
@ -213,8 +227,6 @@
D6C687F7272CD27700874C10 /* Assets.xcassets */,
D6C687F9272CD27700874C10 /* LaunchScreen.storyboard */,
D6C687FC272CD27700874C10 /* Info.plist */,
D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */,
D6E2434F278B62F60005E546 /* Item.swift */,
);
path = Reader;
sourceTree = "<group>";
@ -436,12 +448,16 @@
buildActionMask = 2147483647;
files = (
D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */,
D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */,
D65B18B627504920004A9448 /* FervorController.swift in Sources */,
D6C687EC272CD27600874C10 /* AppDelegate.swift in Sources */,
D6C687F6272CD27600874C10 /* Reader.xcdatamodeld in Sources */,
D6A8A33727766EA100CCEC72 /* ManagedObjectExtensions.swift in Sources */,
D6E2435F278B97240005E546 /* Group+CoreDataClass.swift in Sources */,
D6E2435D278B97240005E546 /* Item+CoreDataClass.swift in Sources */,
D6E24360278B97240005E546 /* Group+CoreDataProperties.swift in Sources */,
D6E2434C278B456A0005E546 /* ItemsViewController.swift in Sources */,
D6E24350278B62F60005E546 /* Item.swift in Sources */,
D6E2435E278B97240005E546 /* Item+CoreDataProperties.swift in Sources */,
D6E24358278B96E40005E546 /* Feed+CoreDataProperties.swift in Sources */,
D65B18BE275051A1004A9448 /* LocalData.swift in Sources */,
D65B18B22750469D004A9448 /* LoginViewController.swift in Sources */,
D65B18C127505348004A9448 /* HomeViewController.swift in Sources */,

View File

@ -0,0 +1,30 @@
//
// Feed+CoreDataClass.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
import Fervor
@objc(Feed)
public class Feed: NSManagedObject {
func updateFromServer(_ serverFeed: Fervor.Feed) {
guard self.id == nil || self.id == serverFeed.id else { return }
self.id = serverFeed.id
self.title = serverFeed.title
self.url = serverFeed.url
self.lastUpdated = serverFeed.lastUpdated
// todo: check this
self.removeFromGroups(self.groups!.filtered(using: NSPredicate(format: "NOT id IN %@", serverFeed.groupIDs)) as NSSet)
let groupsToAddReq = Group.fetchRequest()
groupsToAddReq.predicate = NSPredicate(format: "id IN %@", serverFeed.groupIDs.filter { g in !self.groups!.contains { ($0 as! Group).id == g } })
let groupsToAdd = try! self.managedObjectContext!.fetch(groupsToAddReq)
self.addToGroups(NSSet(array: groupsToAdd))
}
}

View File

@ -0,0 +1,64 @@
//
// Feed+CoreDataProperties.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
extension Feed {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Feed> {
return NSFetchRequest<Feed>(entityName: "Feed")
}
@NSManaged public var id: String?
@NSManaged public var lastUpdated: Date?
@NSManaged public var title: String?
@NSManaged public var url: URL?
@NSManaged public var groups: NSSet?
@NSManaged public var items: NSSet?
}
// MARK: Generated accessors for groups
extension Feed {
@objc(addGroupsObject:)
@NSManaged public func addToGroups(_ value: Group)
@objc(removeGroupsObject:)
@NSManaged public func removeFromGroups(_ value: Group)
@objc(addGroups:)
@NSManaged public func addToGroups(_ values: NSSet)
@objc(removeGroups:)
@NSManaged public func removeFromGroups(_ values: NSSet)
}
// MARK: Generated accessors for items
extension Feed {
@objc(addItemsObject:)
@NSManaged public func addToItems(_ value: Item)
@objc(removeItemsObject:)
@NSManaged public func removeFromItems(_ value: Item)
@objc(addItems:)
@NSManaged public func addToItems(_ values: NSSet)
@objc(removeItems:)
@NSManaged public func removeFromItems(_ values: NSSet)
}
extension Feed : Identifiable {
}

View File

@ -0,0 +1,24 @@
//
// Group+CoreDataClass.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
import Fervor
@objc(Group)
public class Group: NSManagedObject {
func updateFromServer(_ serverGroup: Fervor.Group) {
guard self.id == nil || self.id == serverGroup.id else { return }
self.id = serverGroup.id
self.title = serverGroup.title
// feeds relationships will be updated after feeds are created in PersistentContainer.sync
}
}

View File

@ -0,0 +1,44 @@
//
// Group+CoreDataProperties.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
extension Group {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Group> {
return NSFetchRequest<Group>(entityName: "Group")
}
@NSManaged public var id: String?
@NSManaged public var title: String
@NSManaged public var feeds: NSSet?
}
// MARK: Generated accessors for feeds
extension Group {
@objc(addFeedsObject:)
@NSManaged public func addToFeeds(_ value: Feed)
@objc(removeFeedsObject:)
@NSManaged public func removeFromFeeds(_ value: Feed)
@objc(addFeeds:)
@NSManaged public func addToFeeds(_ values: NSSet)
@objc(removeFeeds:)
@NSManaged public func removeFromFeeds(_ values: NSSet)
}
extension Group : Identifiable {
}

View File

@ -0,0 +1,33 @@
//
// Item+CoreDataClass.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
import Fervor
@objc(Item)
public class Item: NSManagedObject {
func updateFromServer(_ serverItem: Fervor.Item) {
guard self.id == nil || self.id == serverItem.id else { return }
self.id = serverItem.id
self.author = serverItem.author
self.content = serverItem.content
self.title = serverItem.title
self.read = serverItem.read ?? false
self.published = serverItem.published
self.url = serverItem.url
if self.feed?.id != serverItem.feedID {
let feedReq = Feed.fetchRequest()
feedReq.predicate = NSPredicate(format: "id = %@", serverItem.feedID)
self.feed = try! self.managedObjectContext!.fetch(feedReq).first!
}
}
}

View File

@ -1,27 +1,32 @@
//
// Item.swift
// Item+CoreDataProperties.swift
// Reader
//
// Created by Shadowfacts on 1/9/22.
//
//
import Foundation
import CoreData
@objc(Item)
public final class Item: NSManagedObject {
extension Item {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
return NSFetchRequest<Item>(entityName: "Item")
}
@NSManaged public var author: String?
@NSManaged public var content: String?
@NSManaged public var id: String?
@NSManaged public var title: String?
@NSManaged public var read: Bool
@NSManaged public var published: Date?
@NSManaged public var read: Bool
@NSManaged public var title: String?
@NSManaged public var url: URL?
@NSManaged public var feed: Feed?
}
extension Item : Identifiable {
}

View File

@ -1,58 +0,0 @@
//
// ManagedObjectExtensions.swift
// Reader
//
// Created by Shadowfacts on 12/24/21.
//
import Foundation
import Fervor
extension Group {
func updateFromServer(_ serverGroup: Fervor.Group) {
guard self.id == nil || self.id == serverGroup.id else { return }
self.id = serverGroup.id
self.title = serverGroup.title
// feeds relationships will be updated after feeds are created in PersistentContainer.sync
}
}
extension Feed {
func updateFromServer(_ serverFeed: Fervor.Feed) {
guard self.id == nil || self.id == serverFeed.id else { return }
self.id = serverFeed.id
self.title = serverFeed.title
self.url = serverFeed.url
self.lastUpdated = serverFeed.lastUpdated
// todo: check this
self.removeFromGroups(self.groups!.filtered(using: NSPredicate(format: "NOT id IN %@", serverFeed.groupIDs)) as NSSet)
let groupsToAddReq = Group.fetchRequest()
groupsToAddReq.predicate = NSPredicate(format: "id IN %@", serverFeed.groupIDs.filter { g in !self.groups!.contains { ($0 as! Group).id == g } })
let groupsToAdd = try! self.managedObjectContext!.fetch(groupsToAddReq)
self.addToGroups(NSSet(array: groupsToAdd))
}
}
extension Item {
func updateFromServer(_ serverItem: Fervor.Item) {
guard self.id == nil || self.id == serverItem.id else { return }
self.id = serverItem.id
self.author = serverItem.author
self.content = serverItem.content
self.title = serverItem.title
self.read = serverItem.read ?? false
self.published = serverItem.published
self.url = serverItem.url
if self.feed?.id != serverItem.feedID {
let feedReq = Feed.fetchRequest()
feedReq.predicate = NSPredicate(format: "id = %@", serverItem.feedID)
self.feed = try! self.managedObjectContext!.fetch(feedReq).first!
}
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21C52" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Feed" representedClassName="Feed" syncable="YES" codeGenerationType="class">
<entity name="Feed" representedClassName="Feed" syncable="YES">
<attribute name="id" attributeType="String"/>
<attribute name="lastUpdated" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="title" attributeType="String"/>
@ -8,7 +8,7 @@
<relationship name="groups" toMany="YES" deletionRule="Nullify" destinationEntity="Group" inverseName="feeds" inverseEntity="Group"/>
<relationship name="items" toMany="YES" deletionRule="Nullify" destinationEntity="Item" inverseName="feed" inverseEntity="Item"/>
</entity>
<entity name="Group" representedClassName="Group" syncable="YES" codeGenerationType="class">
<entity name="Group" representedClassName="Group" syncable="YES">
<attribute name="id" attributeType="String"/>
<attribute name="title" attributeType="String"/>
<relationship name="feeds" toMany="YES" deletionRule="Nullify" destinationEntity="Feed" inverseName="groups" inverseEntity="Feed"/>

View File

@ -95,8 +95,7 @@ extension HomeViewController {
var title: String {
switch self {
case let .group(group):
// todo: manual codegen for models so this force unwrap isn't necessary
return group.title!
return group.title
case let .feed(feed):
return feed.title!
}