Originally created by @DmitrijMaz on GitHub (Jul 27, 2018).
Hi,
Prerequisites:
CoreStore (5.1.1)
Sample NSManagedObject subclass. Others use the same principle for importing/updating
Every NSManagedObject subclass have uniqueConstraints setup (usually its id)
infixoperator<<->:AssignmentPrecedence/// Assignment operator that checks values for equality before assigning////// - Parameters:/// - to: Destination for assignment. Will only be assigned to `from` if they are not equal/// - from: Source for assignment.func<<-><T>(to:inoutT,from:T)whereT:Equatable{ifto==from{return}to=from}/// Assignment operator that checks values for equality and unwraps before assigning////// - Parameters:/// - to: Destination for assignment. Will only be assigned to `from` if they are not equal, and `from` is not `nil`/// - from: Source for assignment.func<<-><T>(to:inoutT,from:T?)whereT:Equatable{guardletfrom=fromelse{return}to<<->from}
The data is loaded from an API and imported using the code i've provided.
The results are the following:
Memory instrument trace:
Any help would be much appreciated. Contact me if more detailed information is needed.
Thanks!
Originally created by @DmitrijMaz on GitHub (Jul 27, 2018).
Hi,
Prerequisites:
**CoreStore (5.1.1)**
Sample `NSManagedObject` subclass. Others use the same principle for importing/updating
Every `NSManagedObject` subclass have `uniqueConstraints` setup (usually its `id`)
```swift
infix operator <<->: AssignmentPrecedence
/// Assignment operator that checks values for equality before assigning
///
/// - Parameters:
/// - to: Destination for assignment. Will only be assigned to `from` if they are not equal
/// - from: Source for assignment.
func <<-> <T>(to: inout T, from: T) where T: Equatable {
if to == from {
return
}
to = from
}
/// Assignment operator that checks values for equality and unwraps before assigning
///
/// - Parameters:
/// - to: Destination for assignment. Will only be assigned to `from` if they are not equal, and `from` is not `nil`
/// - from: Source for assignment.
func <<-> <T>(to: inout T, from: T?) where T: Equatable {
guard let from = from else { return }
to <<-> from
}
```
```swift
public final class Transfer: NSManagedObject {
static let dateFormatter: DateFormatter = makeDateFormatter()
@objc
public enum Probability: Int16, Equatable & Decodable {
case confirmed = 1
case rumor = 2
case doubtful = 3
}
@objc
public enum Mode: Int16, Equatable & Decodable {
case contractExtension = 1
case transfer = 2
case loan = 3
case returns = 4
}
// MARK: Public
@NSManaged private(set) var id: UniqueIDType
@NSManaged private(set) var date: NSDate
@NSManaged private(set) var daySection: NSNumber?
// MARK: Relationship
@NSManaged private(set) var fromTeam: Team?
@NSManaged private(set) var toTeam: Team?
@NSManaged private(set) var player: Player?
// MARK: Private
@NSManaged private(set) var sa_probability: Probability.RawValue
@NSManaged private(set) var sa_type: Mode.RawValue
}
public extension Transfer {
var icon: Images.Transfer {
switch (probability, type) {
case (.confirmed, .transfer): return .confirmed
case (_, .transfer): return .rumor
case (_, .loan): return .loan
case (_, .contractExtension): return .contractExtension
case (_, .returns): return .upDown
}
}
var probability: Probability {
return Probability(rawValue: sa_probability)!
}
var type: Mode {
return Mode(rawValue: sa_type)!
}
func date(withFormat format: String) -> String {
Transfer.dateFormatter.dateFormat = format
return Transfer.dateFormatter.string(from: date as Date)
}
}
extension Transfer: ImportableUniqueObject {
public typealias UniqueIDType = Int64
public static var uniqueIDKeyPath: String { return #keyPath(Transfer.id) }
public struct ImportSource: Decodable {
let id: UniqueIDType
let fromTeam: Team.ImportSource
let toTeam: Team.ImportSource
let player: Player.ImportSource
let transferProbabilityType: Probability
let transferType: Mode
let transferDate: Date
}
public static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> UniqueIDType? {
return source.id
}
public func update(from source: ImportSource, in transaction: BaseDataTransaction) throws {
id <<-> source.id
sa_probability <<-> source.transferProbabilityType.rawValue
sa_type <<-> source.transferType.rawValue
date <<-> source.transferDate as NSDate
daySection <<-> Int64(date(withFormat: "yyyyMMdd")).flatMap(NSNumber.init)
fromTeam = try transaction.importUniqueObject(Into<Team>(), source: source.fromTeam)
toTeam = try transaction.importUniqueObject(Into<Team>(), source: source.toTeam)
player = try transaction.importUniqueObject(Into<Player>(), source: source.player)
}
}
fileprivate extension Transfer {
static func makeDateFormatter() -> DateFormatter {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "UTC")
return formatter
}
}
```
Core store is setup using the following code:
```swift
public func initializeStorage(completion: @escaping (Result<(), StorageService.Errors>) -> Void) throws -> Progress? {
guard dataStack == .none else {
throw StorageService.Errors.alreadyInitialized
}
dataStack = DataStack(
xcodeModelName: "<app_name>"
)
let storage = getStorage()
App.logger?[.db].log(
level: .debug,
formatLog("Initialize Start", body: "\(storage)")
)
defer {
CoreStore.defaultStack = dataStack
}
let storeCompletion: (Result<(), CoreStoreError>) -> Void = { (result) in
switch result {
case .success:
App.logger?[.db].log(
level: .debug,
self.formatLog("Initialize End", body: "Data stack\n\(CoreStore.defaultStack)")
)
completion(.success(()))
case .failure(let error):
completion(
.failure(.initializationError(error))
)
}
}
switch storage {
case let localStorage as SQLiteStore:
return dataStack.addStorage(localStorage) { storeCompletion($0.asResult()) }
case let inMemory as InMemoryStore:
dataStack.addStorage(inMemory) { storeCompletion($0.asResult()) }
return nil
default:
fatalError("Unknown storage \(storage)")
}
}
```
I have 5 screens that use `ListMonitor` to display the same object, just with a diffrent `Where` clauses
```swift
let from = From<Transfer>()
let sectionBy = SectionBy<Transfer>(\.daySection)
let fetchClauses = fetchClauseProvider(from)
App.storage.monitorSectionedList(
createAsynchronously: { [weak self] (listMonitor) in
self?.listMonitor = listMonitor
handler(listMonitor)
},
from,
sectionBy,
fetchClauses
)
```
The data is loaded from an API and imported using the code i've provided.
The results are the following:

Memory instrument trace:

Any help would be much appreciated. Contact me if more detailed information is needed.
Thanks!
Hi, thanks for the detailed info. May I ask how getStorage() creates your SQLiteStore?
Also, are Transfer objects managed in the SQLiteStore or the InMemoryStore?
@JohnEstropia commented on GitHub (Jul 28, 2018):
Hi, thanks for the detailed info. May I ask how `getStorage()` creates your `SQLiteStore`?
Also, are `Transfer` objects managed in the `SQLiteStore` or the `InMemoryStore`?
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @DmitrijMaz on GitHub (Jul 27, 2018).
Hi,
Prerequisites:
CoreStore (5.1.1)
Sample
NSManagedObjectsubclass. Others use the same principle for importing/updatingEvery
NSManagedObjectsubclass haveuniqueConstraintssetup (usually itsid)Core store is setup using the following code:
I have 5 screens that use
ListMonitorto display the same object, just with a diffrentWhereclausesThe data is loaded from an API and imported using the code i've provided.
The results are the following:

Memory instrument trace:

Any help would be much appreciated. Contact me if more detailed information is needed.
Thanks!
@JohnEstropia commented on GitHub (Jul 28, 2018):
Hi, thanks for the detailed info. May I ask how
getStorage()creates yourSQLiteStore?Also, are
Transferobjects managed in theSQLiteStoreor theInMemoryStore?@ghost commented on GitHub (Jul 28, 2018):
Its created using local option storage with .recreateStoreOnMismatch
Everything is in sqlite store
@DmitrijMaz commented on GitHub (Jul 30, 2018):
I was doing all this in
defaultmode