Use manual codegen for CoreData models
This commit is contained in:
parent
2b38b883fe
commit
eded49b266
|
@ -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 */,
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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!
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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"/>
|
|
@ -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!
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue