Turn ObjectCache into DatabaseObjectCache — rather than a generic with a keypath, it works with DatabaseObject, which has a known databaseID property.

This commit is contained in:
Brent Simmons 2017-08-20 16:03:09 -07:00
parent 2ce577e9d4
commit 213b1d7a6f
4 changed files with 87 additions and 105 deletions

View File

@ -33,7 +33,7 @@
84419AE71B5ABD7F00C26BB2 /* RSDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 84419ADD1B5ABD7F00C26BB2 /* RSDatabaseQueue.m */; };
84419B051B5ABFF700C26BB2 /* FMResultSet+RSExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 84419B031B5ABFF700C26BB2 /* FMResultSet+RSExtras.h */; settings = {ATTRIBUTES = (Public, ); }; };
84419B061B5ABFF700C26BB2 /* FMResultSet+RSExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 84419B041B5ABFF700C26BB2 /* FMResultSet+RSExtras.m */; };
844D97411F2D32F300CEDDEA /* ObjectCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844D97401F2D32F300CEDDEA /* ObjectCache.swift */; };
844D97411F2D32F300CEDDEA /* DatabaseObjectCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844D97401F2D32F300CEDDEA /* DatabaseObjectCache.swift */; };
849BF8C61C94FB8E0071D1DA /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 849BF8C51C94FB8E0071D1DA /* libsqlite3.tbd */; };
84ABC1D11F364B07000DCC55 /* DatabaseLookupTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84ABC1D01F364B07000DCC55 /* DatabaseLookupTable.swift */; };
84ABC1D21F364B07000DCC55 /* DatabaseLookupTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84ABC1D01F364B07000DCC55 /* DatabaseLookupTable.swift */; };
@ -72,7 +72,7 @@
84419ADD1B5ABD7F00C26BB2 /* RSDatabaseQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RSDatabaseQueue.m; path = RSDatabase/RSDatabaseQueue.m; sourceTree = "<group>"; };
84419B031B5ABFF700C26BB2 /* FMResultSet+RSExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "FMResultSet+RSExtras.h"; path = "RSDatabase/FMResultSet+RSExtras.h"; sourceTree = "<group>"; };
84419B041B5ABFF700C26BB2 /* FMResultSet+RSExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "FMResultSet+RSExtras.m"; path = "RSDatabase/FMResultSet+RSExtras.m"; sourceTree = "<group>"; };
844D97401F2D32F300CEDDEA /* ObjectCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ObjectCache.swift; path = RSDatabase/ObjectCache.swift; sourceTree = "<group>"; };
844D97401F2D32F300CEDDEA /* DatabaseObjectCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DatabaseObjectCache.swift; path = RSDatabase/DatabaseObjectCache.swift; sourceTree = "<group>"; };
849BF8C51C94FB8E0071D1DA /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
84ABC1D01F364B07000DCC55 /* DatabaseLookupTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DatabaseLookupTable.swift; path = RSDatabase/DatabaseLookupTable.swift; sourceTree = "<group>"; };
84C6DD001F395C13009AFB47 /* DatabaseObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DatabaseObject.swift; path = RSDatabase/DatabaseObject.swift; sourceTree = "<group>"; };
@ -163,7 +163,7 @@
840405DA1F1C158C00DF0296 /* DatabaseTable.swift */,
84C6DD001F395C13009AFB47 /* DatabaseObject.swift */,
84ABC1D01F364B07000DCC55 /* DatabaseLookupTable.swift */,
844D97401F2D32F300CEDDEA /* ObjectCache.swift */,
844D97401F2D32F300CEDDEA /* DatabaseObjectCache.swift */,
84DDF18A1C94FC45005E6CF5 /* FMDB */,
84F22C5A1B52E0D9000060CE /* Info.plist */,
849BF8C51C94FB8E0071D1DA /* libsqlite3.tbd */,
@ -381,7 +381,7 @@
84DDF1A01C94FC45005E6CF5 /* FMResultSet.m in Sources */,
84419B061B5ABFF700C26BB2 /* FMResultSet+RSExtras.m in Sources */,
84DDF1991C94FC45005E6CF5 /* FMDatabaseAdditions.m in Sources */,
844D97411F2D32F300CEDDEA /* ObjectCache.swift in Sources */,
844D97411F2D32F300CEDDEA /* DatabaseObjectCache.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -231,7 +231,8 @@ private extension DatabaseLookupTable {
func fetchRelatedObjectsWithIDs(_ relatedObjectIDs: Set<String>, _ database: FMDatabase) -> [DatabaseObject]? {
guard let relatedObjects = relatedTable?.fetchObjectsWithIDs(relatedObjectIDs, in: database), !relatedObjects.isEmpty else {
let relatedObjects = relatedTable.fetchObjectsWithIDs(relatedObjectIDs, in: database)
if relatedObjects.isEmpty {
return nil
}
return relatedObjects

View File

@ -0,0 +1,81 @@
//
// DatabaseObjectCache.swift
// RSDatabase
//
// Created by Brent Simmons on 7/29/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
// Not thread-safe.
public final class DatabaseObjectCache {
private var dictionary = [String: DatabaseObject]()
public func addObjects(_ objects: [DatabaseObject]) {
objects.forEach { add($0) }
}
public func addObjectsNotCached(_ objects: [DatabaseObject]) {
objects.forEach { addIfNotCached($0) }
}
public func add(_ object: DatabaseObject) {
self[object.databaseID] = object
}
public func addIfNotCached(_ object: DatabaseObject) {
let identifier = object.databaseID
if let _ = self[identifier] {
return
}
self[identifier] = object
}
public func removeObjects(_ objects: [DatabaseObject]) {
objects.forEach { removeObject($0) }
}
public func removeObject(_ object: DatabaseObject) {
self[object.databaseID] = nil
}
public func uniquedObjects(_ objects: [DatabaseObject]) -> [DatabaseObject] {
// Return cached version of each object.
// When an object is not already cached, cache it,
// then consider that version the unique version.
return objects.map { (object) -> DatabaseObject in
if let cachedObject = self[object.databaseID] {
return cachedObject
}
add(object)
return object
}
}
public func objectWithIDIsCached(_ identifier: String) -> Bool {
return self[identifier] != nil
}
public subscript(_ identifier: String) -> DatabaseObject? {
get {
return dictionary[identifier]
}
set {
dictionary[identifier] = newValue
}
}
}

View File

@ -1,100 +0,0 @@
//
// ObjectCache.swift
// RSDatabase
//
// Created by Brent Simmons on 7/29/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
// Not thread-safe.
public final class ObjectCache<T> {
private let keyPathForID: KeyPath<T,String>
private var dictionary = [String: T]()
public init(keyPathForID: KeyPath<T,String>) {
self.keyPathForID = keyPathForID
}
public func addObjects(_ objects: [T]) {
objects.forEach { add($0) }
}
public func addObjectsNotCached(_ objects: [T]) {
objects.forEach { addIfNotCached($0) }
}
public func add(_ object: T) {
let identifier = identifierForObject(object)
self[identifier] = object
}
public func addIfNotCached(_ object: T) {
let identifier = identifierForObject(object)
if let _ = self[identifier] {
return
}
self[identifier] = object
}
public func removeObjects(_ objects: [T]) {
objects.forEach { removeObject($0) }
}
public func removeObject(_ object: T) {
let identifier = identifierForObject(object)
self[identifier] = nil
}
public func uniquedObjects(_ objects: [T]) -> [T] {
// Return cached version of each object.
// When an object is not already cached, cache it,
// then consider that version the unique version.
return objects.map { (object) -> T in
let identifier = identifierForObject(object)
if let cachedObject = self[identifier] {
return cachedObject
}
add(object)
return object
}
}
public func objectWithIDIsCached(_ identifier: String) -> Bool {
if let _ = self[identifier] {
return true
}
return false
}
public subscript(_ identifier: String) -> T? {
get {
return dictionary[identifier]
}
set {
dictionary[identifier] = newValue
}
}
}
private extension ObjectCache {
func identifierForObject(_ object: T) -> String {
return object[keyPath: keyPathForID]
}
}