-
-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
281 additions
and
65 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import Foundation | ||
import CoreData | ||
|
||
public class DATAFilter: NSObject { | ||
public struct Operation : OptionSetType { | ||
public let rawValue: Int | ||
|
||
public init(rawValue: Int) { | ||
self.rawValue = rawValue | ||
} | ||
|
||
public static let Insert = Operation(rawValue: 1 << 0) | ||
public static let Update = Operation(rawValue: 1 << 1) | ||
public static let Delete = Operation(rawValue: 1 << 2) | ||
public static let All: Operation = [.Insert, .Update, .Delete] | ||
} | ||
|
||
public class func changes(changes: [[String : AnyObject]], | ||
inEntityNamed entityName: String, | ||
localPrimaryKey: String, | ||
remotePrimaryKey: String, | ||
context: NSManagedObjectContext, | ||
inserted: (JSON: [String : AnyObject]) -> Void, | ||
updated: (JSON: [String : AnyObject], updatedObject: NSManagedObject) -> Void){ | ||
self.changes(changes, inEntityNamed: entityName, predicate: nil, operations: .All, localPrimaryKey: localPrimaryKey, remotePrimaryKey: remotePrimaryKey, context: context, inserted: inserted, updated: updated) | ||
} | ||
|
||
public class func changes(changes: [[String : AnyObject]], | ||
inEntityNamed entityName: String, | ||
predicate: NSPredicate?, | ||
operations: Operation, | ||
localPrimaryKey: String, | ||
remotePrimaryKey: String, | ||
context: NSManagedObjectContext, | ||
inserted: (JSON: [String : AnyObject]) -> Void, | ||
updated: (JSON: [String : AnyObject], 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 = DATAObjectIDs.objectIDs(inEntityNamed: entityName, withAttributesNamed: localPrimaryKey, context: context, predicate: predicate) as? [NSObject : NSManagedObjectID] ?? [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 : AnyObject]]() | ||
for (primaryKey, change) in zip(remotePrimaryKeysWithoutNils, changes) { | ||
remotePrimaryKeysAndChanges[primaryKey] = change | ||
} | ||
|
||
var intersection = Set(remotePrimaryKeysWithoutNils) | ||
intersection.intersectInPlace(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.objectWithID(objectID) | ||
context.deleteObject(object) | ||
} | ||
} | ||
|
||
if operations.contains(.Insert) { | ||
for fetchedID in insertedObjectIDs { | ||
let objectDictionary = remotePrimaryKeysAndChanges[fetchedID]! | ||
inserted(JSON: objectDictionary) | ||
} | ||
} | ||
|
||
if operations.contains(.Update) { | ||
for fetchedID in updatedObjectIDs { | ||
let JSON = remotePrimaryKeysAndChanges[fetchedID]! | ||
let objectID = primaryKeysAndObjectIDs[fetchedID]! | ||
let object = context.objectWithID(objectID) | ||
updated(JSON: JSON, updatedObject: object) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import CoreData | ||
|
||
public class DATAObjectIDs: NSObject { | ||
public class func objectIDs(inEntityNamed entityName: String, withAttributesNamed attributeName: String, context: NSManagedObjectContext, predicate: NSPredicate?) -> [NSObject: AnyObject] { | ||
return self.generateObjectIDs(inEntityNamed: entityName, withAttributesNamed: attributeName, context: context, predicate: predicate, sortDescriptors: nil) | ||
} | ||
|
||
class func generateObjectIDs(inEntityNamed entityName: String, withAttributesNamed attributeName: String, context: NSManagedObjectContext, predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor]?) -> [NSObject: AnyObject] { | ||
var result = [NSObject: AnyObject]() | ||
|
||
context.performBlockAndWait { | ||
let expression = NSExpressionDescription() | ||
expression.name = "objectID" | ||
expression.expression = NSExpression.expressionForEvaluatedObject() | ||
expression.expressionResultType = .ObjectIDAttributeType | ||
|
||
let request = NSFetchRequest(entityName: entityName) | ||
request.predicate = predicate | ||
request.resultType = .DictionaryResultType | ||
request.propertiesToFetch = [expression, attributeName] | ||
request.sortDescriptors = sortDescriptors | ||
|
||
do { | ||
let objects = try context.executeFetchRequest(request) | ||
for object in objects { | ||
let fetchedID = object[attributeName] as! NSObject | ||
let objectID = object["objectID"] as! NSManagedObjectID | ||
|
||
if let _ = result[fetchedID] { | ||
context.deleteObject(context.objectWithID(objectID)) | ||
} else { | ||
result[fetchedID] = objectID | ||
} | ||
} | ||
} catch let error as NSError { | ||
print("error: \(error)") | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
class func generateObjectIDs(inEntityNamed entityName: String, context: NSManagedObjectContext, predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor]?) -> [Any] { | ||
var objectIDs = [NSManagedObjectID]() | ||
|
||
context.performBlockAndWait { | ||
let request = NSFetchRequest(entityName: entityName) | ||
request.predicate = predicate; | ||
request.resultType = .ManagedObjectIDResultType | ||
|
||
do { | ||
objectIDs = try context.executeFetchRequest(request) as? [NSManagedObjectID] ?? [NSManagedObjectID]() | ||
} catch let error as NSError { | ||
print("error: \(error)") | ||
} | ||
} | ||
|
||
return objectIDs | ||
} | ||
|
||
class func generateAttributes(inEntityNamed entityName: String, attributeName: String, context: NSManagedObjectContext, predicate: NSPredicate?, sortDescriptors: [NSSortDescriptor]?) -> [Any] { | ||
var attributes = [Any]() | ||
|
||
context.performBlockAndWait { | ||
let expression = NSExpressionDescription() | ||
expression.name = "objectID" | ||
expression.expression = NSExpression.expressionForEvaluatedObject() | ||
expression.expressionResultType = .ObjectIDAttributeType | ||
|
||
let request = NSFetchRequest(entityName: entityName) | ||
request.predicate = predicate | ||
request.resultType = .DictionaryResultType | ||
request.propertiesToFetch = [expression, attributeName] | ||
request.sortDescriptors = sortDescriptors | ||
|
||
do { | ||
let objects = try context.executeFetchRequest(request) | ||
for object in objects { | ||
if let fetchedID = object[attributeName] { | ||
attributes.append(fetchedID) | ||
} | ||
} | ||
} catch let error as NSError { | ||
print("error: \(error)") | ||
} | ||
} | ||
|
||
return attributes | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
4 changes: 1 addition & 3 deletions
4
Source/NSManagedObject+Sync.swift → Source/Sync/NSManagedObject+Sync.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
Source/NSManagedObjectContext+Sync.swift → ...ce/Sync/NSManagedObjectContext+Sync.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import Foundation | ||
|
||
@objc public class TestCheck: NSObject { | ||
/** | ||
Method to check wheter your on testing mode or not. | ||
- returns: A Bool, `true` if you're on testing mode, `false` if you're not. | ||
*/ | ||
public static let isTesting: Bool = { | ||
let enviroment = NSProcessInfo.processInfo().environment | ||
let serviceName = enviroment["XPC_SERVICE_NAME"] | ||
let injectBundle = enviroment["XCInjectBundle"] | ||
var isRunning = (enviroment["TRAVIS"] != nil || enviroment["XCTestConfigurationFilePath"] != nil) | ||
|
||
if !isRunning { | ||
if let serviceName = serviceName { | ||
isRunning = (serviceName as NSString).pathExtension == "xctest" | ||
} | ||
} | ||
|
||
if !isRunning { | ||
if let injectBundle = injectBundle { | ||
isRunning = (injectBundle as NSString).pathExtension == "xctest" | ||
} | ||
} | ||
|
||
return isRunning | ||
}() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters