Skip to content

Commit

Permalink
Add files
Browse files Browse the repository at this point in the history
  • Loading branch information
3lvis committed Mar 16, 2017
1 parent 1a8e46f commit 31050be
Show file tree
Hide file tree
Showing 22 changed files with 3,229 additions and 0 deletions.
90 changes: 90 additions & 0 deletions Source/DataFilter/DataFilter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Foundation
import CoreData

/**
Helps you filter insertions, deletions and updates by comparing your JSON dictionary with your Core Data local objects.
It also provides uniquing for you locally stored objects and automatic removal of not found ones.
*/
class DataFilter: NSObject {
struct Operation: OptionSet {
let rawValue: Int

init(rawValue: Int) {
self.rawValue = rawValue
}

static let insert = Operation(rawValue: 1 << 0)
static let update = Operation(rawValue: 1 << 1)
static let delete = Operation(rawValue: 1 << 2)
static let all: Operation = [.insert, .update, .delete]
}

class func changes(_ changes: [[String: Any]],
inEntityNamed entityName: String,
localPrimaryKey: String,
remotePrimaryKey: String,
context: NSManagedObjectContext,
inserted: (_ json: [String: Any]) -> Void,
updated: (_ json: [String: Any], _ updatedObject: NSManagedObject) -> Void) {
self.changes(changes, inEntityNamed: entityName, predicate: nil, operations: .all, localPrimaryKey: localPrimaryKey, remotePrimaryKey: remotePrimaryKey, context: context, inserted: inserted, updated: updated)
}

class func changes(_ changes: [[String: Any]],
inEntityNamed entityName: String,
predicate: NSPredicate?,
operations: Operation,
localPrimaryKey: String,
remotePrimaryKey: String,
context: NSManagedObjectContext,
inserted: (_ json: [String: Any]) -> Void,
updated: (_ json: [String: Any], _ updatedObject: NSManagedObject) -> Void) {
// `DataObjectIDs.objectIDsInEntityNamed` also deletes all objects that don't have a primary key or that have the same primary key already found in the context
let primaryKeysAndObjectIDs = context.managedObjectIDs(in: entityName, usingAsKey: localPrimaryKey, predicate: predicate) as [NSObject: NSManagedObjectID]
let localPrimaryKeys = Array(primaryKeysAndObjectIDs.keys)
let remotePrimaryKeys = changes.map { $0[remotePrimaryKey] }
let remotePrimaryKeysWithoutNils = (remotePrimaryKeys.filter { (($0 as? NSObject) != NSNull()) && ($0 != nil) } as! [NSObject?]) as! [NSObject]

var remotePrimaryKeysAndChanges = [NSObject: [String: Any]]()
for (primaryKey, change) in zip(remotePrimaryKeysWithoutNils, changes) {
remotePrimaryKeysAndChanges[primaryKey] = change
}

var intersection = Set(remotePrimaryKeysWithoutNils)
intersection.formIntersection(Set(localPrimaryKeys))
let updatedObjectIDs = Array(intersection)

var deletedObjectIDs = localPrimaryKeys
deletedObjectIDs = deletedObjectIDs.filter { value in
!remotePrimaryKeysWithoutNils.contains { $0.isEqual(value) }
}

var insertedObjectIDs = remotePrimaryKeysWithoutNils
insertedObjectIDs = insertedObjectIDs.filter { value in
!localPrimaryKeys.contains { $0.isEqual(value) }
}

if operations.contains(.delete) {
for fetchedID in deletedObjectIDs {
let objectID = primaryKeysAndObjectIDs[fetchedID]!
let object = context.object(with: objectID)
context.delete(object)
}
}

if operations.contains(.insert) {
for fetchedID in insertedObjectIDs {
let objectDictionary = remotePrimaryKeysAndChanges[fetchedID]!
inserted(objectDictionary)
}
}

if operations.contains(.update) {
for fetchedID in updatedObjectIDs {
let JSON = remotePrimaryKeysAndChanges[fetchedID]!
let objectID = primaryKeysAndObjectIDs[fetchedID]!
let object = context.object(with: objectID)
updated(JSON, object)
}
}
}
}
Loading

0 comments on commit 31050be

Please sign in to comment.