From 41d8a7f3de7e4ed27400888a67e151a80cb4b9f2 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 3 Jul 2017 15:04:31 -0700 Subject: [PATCH] Continue surgery. Still broken build. --- Frameworks/Data/ArticleStatus.swift | 14 ++-- Frameworks/Database/Constants.swift | 28 +++++++ Frameworks/Database/CreateStatements.sql | 6 +- Frameworks/Database/Database.swift | 83 ++++--------------- .../Database.xcodeproj/project.pbxproj | 28 +++++++ .../Extensions/Article+Database.swift | 26 ++++++ .../Extensions/ArticleStatus+Database.swift | 52 ++++++++++++ .../Database/Extensions/Folder+Database.swift | 18 ++++ .../Database/PropertyListTransformer.swift | 54 ++++++++++++ Frameworks/Database/StatusesManager.swift | 18 ++-- 10 files changed, 239 insertions(+), 88 deletions(-) create mode 100644 Frameworks/Database/Constants.swift create mode 100644 Frameworks/Database/Extensions/Article+Database.swift create mode 100644 Frameworks/Database/Extensions/ArticleStatus+Database.swift create mode 100644 Frameworks/Database/Extensions/Folder+Database.swift create mode 100644 Frameworks/Database/PropertyListTransformer.swift diff --git a/Frameworks/Data/ArticleStatus.swift b/Frameworks/Data/ArticleStatus.swift index 56bb9f50a..da77bdd1b 100644 --- a/Frameworks/Data/ArticleStatus.swift +++ b/Frameworks/Data/ArticleStatus.swift @@ -21,20 +21,22 @@ public final class ArticleStatus: Hashable { public var starred = false public var userDeleted = false public var dateArrived: Date - var accountInfo: AccountInfo? + public let articleID: String + public var accountInfo: AccountInfo? public let hashValue: Int - init(read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date, accountInfo: AccountInfo?) { + public init(articleID: String, read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date, accountInfo: AccountInfo?) { + self.articleID = articleID self.read = read self.starred = starred self.userDeleted = userDeleted self.dateArrived = dateArrived self.accountInfo = accountInfo - self.hashValue = dateArrived.hashValue + self.hashValue = articleID.hashValue } - func boolStatusForKey(_ key: String) -> Bool { + public func boolStatus(forKey key: String) -> Bool { if let articleStatusKey = ArticleStatusKey(rawValue: key) { switch articleStatusKey { @@ -52,7 +54,7 @@ public final class ArticleStatus: Hashable { return false } - func setBoolStatusForKey(_ status: Bool, key: String) { + public func setBoolStatus(_ status: Bool, forKey key: String) { if let articleStatusKey = ArticleStatusKey(rawValue: key) { switch articleStatusKey { @@ -74,6 +76,6 @@ public final class ArticleStatus: Hashable { public class func ==(lhs: ArticleStatus, rhs: ArticleStatus) -> Bool { - return lhs.dateArrived == rhs.dateArrived && lhs.read == rhs.read && lhs.starred == rhs.starred + return lhs.articleID == rhs.articleID && lhs.dateArrived == rhs.dateArrived && lhs.read == rhs.read && lhs.starred == rhs.starred } } diff --git a/Frameworks/Database/Constants.swift b/Frameworks/Database/Constants.swift new file mode 100644 index 000000000..321f85db9 --- /dev/null +++ b/Frameworks/Database/Constants.swift @@ -0,0 +1,28 @@ +// +// Keys.swift +// Database +// +// Created by Brent Simmons on 7/3/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation + +public struct DatabaseTableName { + + static let articles = "articles" + static let statuses = "statuses" +} + +public struct DatabaseKey { + + static let articleID = "articleID" + static let accountInfo = "accountInfo" + + // ArticleStatus + static let read = "read" + static let starred = "starred" + static let userDeleted = "userDeleted" + static let dateArrived = "dateArrived" +} + diff --git a/Frameworks/Database/CreateStatements.sql b/Frameworks/Database/CreateStatements.sql index 1c3951781..0e10c8854 100644 --- a/Frameworks/Database/CreateStatements.sql +++ b/Frameworks/Database/CreateStatements.sql @@ -1,9 +1,5 @@ -/*articleID is a hash of [something]+feedID. When there's a guid, [something] is a guid. Otherwise it's a combination of non-null properties.*/ - CREATE TABLE if not EXISTS articles (articleID TEXT NOT NULL PRIMARY KEY, feedID TEXT NOT NULL, guid TEXT, title TEXT, body TEXT, datePublished DATE, dateModified DATE, link TEXT, permalink TEXT, author TEXT); -CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0); - -/*Indexes*/ +CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0, accountInfo BLOB); CREATE INDEX if not EXISTS feedIndex on articles (feedID); diff --git a/Frameworks/Database/Database.swift b/Frameworks/Database/Database.swift index 9969a6ed6..b91ed4361 100644 --- a/Frameworks/Database/Database.swift +++ b/Frameworks/Database/Database.swift @@ -12,9 +12,9 @@ import RSDatabase import RSParser import Data -let sqlLogging = false +private let sqlLogging = false -func logSQL(_ sql: String) { +private func logSQL(_ sql: String) { if sqlLogging { print("SQL: \(sql)") } @@ -22,9 +22,7 @@ func logSQL(_ sql: String) { typealias ArticleResultBlock = (Set
) -> Void -private let articlesTableName = "articles" - -final class LocalDatabase { +final class Database { fileprivate let queue: RSDatabaseQueue private let databaseFile: String @@ -51,10 +49,6 @@ final class LocalDatabase { func fetchArticlesForFeed(_ feed: Feed) -> Set
{ -// if let articles = articleCache.cachedArticlesForFeedID(feed.feedID) { -// return articles -// } - var fetchedArticles = Set
() let feedID = feed.feedID @@ -63,17 +57,12 @@ final class LocalDatabase { fetchedArticles = self.fetchArticlesForFeedID(feedID, database: database) } - let articles = articleCache.uniquedArticles(fetchedArticles) + let articles = articleCache.uniquedArticles(fetchedArticles, statusesManager: statusesManager) return filteredArticles(articles, feedCounts: [feed.feedID: fetchedArticles.count]) } func fetchArticlesForFeedAsync(_ feed: Feed, _ resultBlock: @escaping ArticleResultBlock) { -// if let articles = articleCache.cachedArticlesForFeedID(feed.feedID) { -// resultBlock(articles) -// return -// } - let feedID = feed.feedID queue.fetch { (database: FMDatabase!) -> Void in @@ -82,7 +71,7 @@ final class LocalDatabase { DispatchQueue.main.async() { () -> Void in - let articles = self.articleCache.uniquedArticles(fetchedArticles) + let articles = self.articleCache.uniquedArticles(fetchedArticles, statusesManager: self.statusesManager) let filteredArticles = self.filteredArticles(articles, feedCounts: [feed.feedID: fetchedArticles.count]) resultBlock(filteredArticles) } @@ -131,13 +120,13 @@ final class LocalDatabase { func fetchUnreadArticlesForFolder(_ folder: Folder) -> Set
{ - return fetchUnreadArticlesForFeedIDs(Array(folder.flattenedFeedIDs)) + return fetchUnreadArticlesForFeedIDs(folder.flattenedFeedIDs()) } func fetchUnreadArticlesForFeedIDs(_ feedIDs: [String]) -> Set
{ if feedIDs.isEmpty { - return Set() + return Set
() } var fetchedArticles = Set
() @@ -158,7 +147,7 @@ final class LocalDatabase { } } - let articles = articleCache.uniquedArticles(fetchedArticles) + let articles = articleCache.uniquedArticles(fetchedArticles, statusesManager: statusesManager) return filteredArticles(articles, feedCounts: counts) } @@ -193,7 +182,7 @@ final class LocalDatabase { fetchArticlesForFeedAsync(feed) { (articles) -> Void in - let articlesDictionary = self.articlesDictionary(articles as NSSet) as! [String: LocalArticle] + let articlesDictionary = self.articlesDictionary(articles as NSSet) as! [String: Article] self.updateArticles(articlesDictionary, parsedArticles: parsedArticlesDictionary, feed: feed, completionHandler: completionHandler) } } @@ -208,7 +197,7 @@ final class LocalDatabase { // MARK: Private -private extension LocalDatabase { +private extension Database { // MARK: Saving Articles @@ -222,7 +211,7 @@ private extension LocalDatabase { articleCache.cacheArticles(newArticles) let newArticleDictionaries = newArticles.map { (oneArticle) in - return oneArticle.databaseDictionary + return oneArticle.databaseDictionary() } queue.update { (database: FMDatabase!) -> Void in @@ -232,7 +221,7 @@ private extension LocalDatabase { for oneDictionary in articleChanges { let oneArticleDictionary = oneDictionary.mutableCopy() as! NSMutableDictionary - let articleID = oneArticleDictionary[articleIDKey]! + let articleID = oneArticleDictionary[DatabaseKey.articleID]! oneArticleDictionary.removeObject(forKey: articleIDKey) let _ = database.rs_updateRows(with: oneArticleDictionary as [NSObject: AnyObject], whereKey: articleIDKey, equalsValue: articleID, tableName: articlesTableName) @@ -292,7 +281,7 @@ private extension LocalDatabase { func createNewArticlesWithParsedArticles(_ parsedArticles: Set, feedID: String) -> Set
{ - return Set(parsedArticles.map { LocalArticle(account: account, feedID: feedID, parsedArticle: $0) }) + return Set(parsedArticles.map { Article(account: account, feedID: feedID, parsedArticle: $0) }) } func articlesWithParsedArticles(_ parsedArticles: Set, feedID: String) -> Set
{ @@ -300,7 +289,7 @@ private extension LocalDatabase { var localArticles = Set
() for oneParsedArticle in parsedArticles { - let oneLocalArticle = LocalArticle(account: self.account, feedID: feedID, parsedArticle: oneParsedArticle) + let oneLocalArticle = Article(account: self.account, feedID: feedID, parsedArticle: oneParsedArticle) localArticles.insert(oneLocalArticle) } @@ -343,7 +332,7 @@ private extension LocalDatabase { return articlesWithResultSet(resultSet) } - return Set() + return Set
() } func articlesWithResultSet(_ resultSet: FMResultSet) -> Set
{ @@ -496,46 +485,4 @@ private extension LocalDatabase { } } } - - func deleteOldArticlesInFeed(_ feed: Feed) { - - numberOfArticlesInFeedID(feed.feedID) { (numberOfArticlesInFeed) in - - if numberOfArticlesInFeed <= LocalDatabase.minimumNumberOfArticlesInFeed { - return - } - - - - - } - - } - - // MARK: Deleting Articles - -// func deleteOldArticles(_ articleIDsInFeeds: Set) { -// -// queue.update { (database: FMDatabase!) -> Void in -// -//// let cutoffDate = NSDate.rs_dateWithNumberOfDaysInThePast(60) -//// let articles = self.fetchArticlesWithWhereClause(database, whereClause: "statuses.dateArrived < ? limit 200", parameters: [cutoffDate]) -// -//// var articleIDsToDelete = Set() -//// -//// for oneArticle in articles { -// // TODO -//// if !localAccountShouldIncludeArticle(oneArticle, articleIDsInFeed: articleIDsInFeeds) { -//// articleIDsToDelete.insert(oneArticle.articleID) -//// } -//// } -// -//// if !articleIDsToDelete.isEmpty { -//// database.rs_deleteRowsWhereKey(articleIDKey, inValues: Array(articleIDsToDelete), tableName: articlesTableName) -//// } -// } -// } - - - } diff --git a/Frameworks/Database/Database.xcodeproj/project.pbxproj b/Frameworks/Database/Database.xcodeproj/project.pbxproj index 5c7b12dc9..36db5d98b 100644 --- a/Frameworks/Database/Database.xcodeproj/project.pbxproj +++ b/Frameworks/Database/Database.xcodeproj/project.pbxproj @@ -9,6 +9,11 @@ /* Begin PBXBuildFile section */ 844BEE411F0AB3AB004AB7CD /* Database.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE371F0AB3AA004AB7CD /* Database.framework */; }; 844BEE461F0AB3AB004AB7CD /* DatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */; }; + 845580671F0AEBCD003CCFA1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580661F0AEBCD003CCFA1 /* Constants.swift */; }; + 845580721F0AEE49003CCFA1 /* PropertyListTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */; }; + 845580761F0AF670003CCFA1 /* Article+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580751F0AF670003CCFA1 /* Article+Database.swift */; }; + 845580781F0AF678003CCFA1 /* Folder+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580771F0AF678003CCFA1 /* Folder+Database.swift */; }; + 8455807A1F0AF67D003CCFA1 /* ArticleStatus+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */; }; 846146271F0ABC7B00870CB3 /* RSParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 846146241F0ABC7400870CB3 /* RSParser.framework */; }; 84E156EA1F0AB80500F8CC05 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E156E91F0AB80500F8CC05 /* Database.swift */; }; 84E156EC1F0AB80E00F8CC05 /* ArticlesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E156EB1F0AB80E00F8CC05 /* ArticlesManager.swift */; }; @@ -83,6 +88,11 @@ 844BEE401F0AB3AB004AB7CD /* DatabaseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DatabaseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseTests.swift; sourceTree = ""; }; 844BEE471F0AB3AB004AB7CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 845580661F0AEBCD003CCFA1 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyListTransformer.swift; sourceTree = ""; }; + 845580751F0AF670003CCFA1 /* Article+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Article+Database.swift"; path = "Extensions/Article+Database.swift"; sourceTree = ""; }; + 845580771F0AF678003CCFA1 /* Folder+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Folder+Database.swift"; path = "Extensions/Folder+Database.swift"; sourceTree = ""; }; + 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "ArticleStatus+Database.swift"; path = "Extensions/ArticleStatus+Database.swift"; sourceTree = ""; }; 8461461E1F0ABC7300870CB3 /* RSParser.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSParser.xcodeproj; path = ../RSParser/RSParser.xcodeproj; sourceTree = ""; }; 84E156E81F0AB75600F8CC05 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 84E156E91F0AB80500F8CC05 /* Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = ""; }; @@ -121,8 +131,11 @@ isa = PBXGroup; children = ( 84E156E91F0AB80500F8CC05 /* Database.swift */, + 845580661F0AEBCD003CCFA1 /* Constants.swift */, 84E156EB1F0AB80E00F8CC05 /* ArticlesManager.swift */, 84E156ED1F0AB81400F8CC05 /* StatusesManager.swift */, + 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */, + 8461462A1F0AC44100870CB3 /* Extensions */, 84E156EF1F0AB81F00F8CC05 /* CreateStatements.sql */, 84E156E81F0AB75600F8CC05 /* Info.plist */, 844BEE441F0AB3AB004AB7CD /* DatabaseTests */, @@ -158,6 +171,16 @@ name = Products; sourceTree = ""; }; + 8461462A1F0AC44100870CB3 /* Extensions */ = { + isa = PBXGroup; + children = ( + 845580771F0AF678003CCFA1 /* Folder+Database.swift */, + 845580751F0AF670003CCFA1 /* Article+Database.swift */, + 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */, + ); + name = Extensions; + sourceTree = ""; + }; 84E156F21F0AB83600F8CC05 /* Products */ = { isa = PBXGroup; children = ( @@ -370,6 +393,11 @@ 84E156EA1F0AB80500F8CC05 /* Database.swift in Sources */, 84E156EC1F0AB80E00F8CC05 /* ArticlesManager.swift in Sources */, 84E156EE1F0AB81400F8CC05 /* StatusesManager.swift in Sources */, + 845580671F0AEBCD003CCFA1 /* Constants.swift in Sources */, + 845580781F0AF678003CCFA1 /* Folder+Database.swift in Sources */, + 845580761F0AF670003CCFA1 /* Article+Database.swift in Sources */, + 845580721F0AEE49003CCFA1 /* PropertyListTransformer.swift in Sources */, + 8455807A1F0AF67D003CCFA1 /* ArticleStatus+Database.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Frameworks/Database/Extensions/Article+Database.swift b/Frameworks/Database/Extensions/Article+Database.swift new file mode 100644 index 000000000..270db7feb --- /dev/null +++ b/Frameworks/Database/Extensions/Article+Database.swift @@ -0,0 +1,26 @@ +// +// Article+Database.swift +// Database +// +// Created by Brent Simmons on 7/3/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation +import RSDatabase +import Data + +extension Article { + + convenience init?(row: FMResultSet) { + + } + + func databaseDictionary() -> NSDictionary { + + var d = NSMutableDictionary() + + + return d.copy() as! NSDictionary + } +} diff --git a/Frameworks/Database/Extensions/ArticleStatus+Database.swift b/Frameworks/Database/Extensions/ArticleStatus+Database.swift new file mode 100644 index 000000000..37b150cf3 --- /dev/null +++ b/Frameworks/Database/Extensions/ArticleStatus+Database.swift @@ -0,0 +1,52 @@ +// +// ArticleStatus+Database.swift +// Database +// +// Created by Brent Simmons on 7/3/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation +import RSDatabase +import Data + +extension ArticleStatus { + + convenience init?(row: FMResultSet) { + + let articleID = row.string(forColumn: DatabaseKey.articleID) + if (articleID == nil) { + return nil + } + let read = row.bool(forColumn: DatabaseKey.read) + let starred = row.bool(forColumn: DatabaseKey.starred) + let userDeleted = row.bool(forColumn: DatabaseKey.userDeleted) + + var dateArrived = row.date(forColumn: DatabaseKey.dateArrived) + if (dateArrived == nil) { + dateArrived = NSDate.distantPast + } + + let accountInfoPlist = PropertyListTransformer.accountInfoWithRow(row) + + self.init(articleID: articleID!, read: read, starred: starred, userDeleted: userDeleted, dateArrived: dateArrived!, accountInfo: accountInfoPlist) + } + + func databaseDictionary() -> NSDictionary { + + let d = NSMutableDictionary() + + d[DatabaseKey.articleID] = articleID + d[DatabaseKey.read] = read + d[DatabaseKey.starred] = starred + d[DatabaseKey.userDeleted] = userDeleted + d[DatabaseKey.dateArrived] = dateArrived + + if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) { + d[DatabaseKey.accountInfo] = data + } + + return d.copy() as! NSDictionary + } +} + diff --git a/Frameworks/Database/Extensions/Folder+Database.swift b/Frameworks/Database/Extensions/Folder+Database.swift new file mode 100644 index 000000000..7579e5d37 --- /dev/null +++ b/Frameworks/Database/Extensions/Folder+Database.swift @@ -0,0 +1,18 @@ +// +// Folder+Database.swift +// Database +// +// Created by Brent Simmons on 7/3/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation +import Data + +extension Folder { + + func flattenedFeedIDs() -> [String] { + + return flattenedFeeds().map { $0.feedID } + } +} diff --git a/Frameworks/Database/PropertyListTransformer.swift b/Frameworks/Database/PropertyListTransformer.swift new file mode 100644 index 000000000..d24dbe8dd --- /dev/null +++ b/Frameworks/Database/PropertyListTransformer.swift @@ -0,0 +1,54 @@ +// +// AccountInfo.swift +// Database +// +// Created by Brent Simmons on 7/3/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation +import RSDatabase +import Data + +// This allows for serializing structures such as Author, Attachment, and AccountInfo +// without having to create separate tables and lookup tables. +// While there are good strong arguments for using separate tables, +// we decided that the relative simplicity this allows is worth it. + +struct PropertyListTransformer { + + static func accountInfoWithRow(_ row: FMResultSet) -> AccountInfo? { + + guard let rawAccountInfo = row.data(forColumn: DatabaseKey.accountInfo) else { + return nil + } + return propertyList(withData: rawAccountInfo) as? AccountInfo + } + + static func propertyListWithRow(_ row: FMResultSet, column: String) -> Any? { + + guard let rawData = row.data(forColumn: column) else { + return nil + } + return propertyList(withData: rawData) + } + + static func propertyList(withData data: Data) -> Any? { + + do { + return try PropertyListSerialization.propertyList(fromData: rawAccountInfo, options: [], format: nil) + } catch { + return nil + } + } + + static func data(withPropertyList plist: Any) -> Data? { + + do { + return try PropertyListSerialization.data(from: plist, format: .binary, options: []) + } + catch { + return nil + } + } +} diff --git a/Frameworks/Database/StatusesManager.swift b/Frameworks/Database/StatusesManager.swift index 9b863d1c1..f9f5ea0a0 100644 --- a/Frameworks/Database/StatusesManager.swift +++ b/Frameworks/Database/StatusesManager.swift @@ -22,7 +22,7 @@ final class StatusesManager { self.queue = queue } - func markArticles(_ articles: Set
, statusKey: ArticleStatusKey, flag: Bool) { + func markArticles(_ articles: Set
, statusKey: String, flag: Bool) { assertNoMissingStatuses(articles) let statuses = Set(articles.flatMap { $0.status }) @@ -36,7 +36,7 @@ final class StatusesManager { if let cachedStatus = cachedStatusForArticleID(oneArticle.articleID) { oneArticle.status = cachedStatus } - else if let oneArticleStatus = oneArticle.status as? ArticleStatus { + else if let oneArticleStatus = oneArticle.status { cacheStatus(oneArticleStatus) } } @@ -85,7 +85,7 @@ private extension StatusesManager { // MARK: Marking - func markArticleStatuses(_ statuses: Set, statusKey: ArticleStatusKey, flag: Bool) { + func markArticleStatuses(_ statuses: Set, statusKey: String, flag: Bool) { // Ignore the statuses where status.[statusKey] == flag. Update the remainder and save in database. @@ -93,8 +93,8 @@ private extension StatusesManager { statuses.forEach { (oneStatus) in - if oneStatus.boolStatusForKey(statusKey) != flag { - oneStatus.setBoolStatusForKey(flag, articleStatusKey: statusKey) + if oneStatus.boolStatus(forKey: statusKey) != flag { + oneStatus.setBoolStatus(flag, forKey: statusKey) articleIDs.insert(oneStatus.articleID) } } @@ -112,7 +112,7 @@ private extension StatusesManager { return Set() } - guard let resultSet = database.rs_selectRowsWhereKey(articleIDKey, inValues: Array(articleIDs), tableName: statusesTableName) else { + guard let resultSet = database.rs_selectRowsWhereKey(DatabaseKey.articleID, inValues: Array(articleIDs), tableName: statusesTableName) else { return Set() } @@ -137,7 +137,7 @@ private extension StatusesManager { func saveStatuses(_ statuses: Set) { let statusArray = statuses.map { (oneStatus) -> NSDictionary in - return oneStatus.databaseDictionary + return oneStatus.databaseDictionary() } queue.update { (database: FMDatabase!) -> Void in @@ -210,9 +210,9 @@ private extension StatusesManager { extension ParsedItem { - var databaseID: String { + var articleID: String { get { - return "\(feedURL) \(uniqueID)" + return "\(feedURL) \(uniqueID)" //Must be same as Article.articleID } } }