This PR contains all the work related to setting up this project as required to implement the [Assignment](https://repo.rock-n-code.com/rock-n-code/deep-linking-assignment/wiki/Assignment) on top, as intended. To summarise this work: - [x] created a new **Xcode** project; - [x] cloned the `Wikipedia` app and inserted it into the **Xcode** project; - [x] created the `Locations` app and also, its `Libraries` package; - [x] created the `Shared` package to share dependencies between the apps; - [x] added a `Makefile` file and implemented some **environment** and **help** commands. Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Reviewed-on: rock-n-code/deep-linking-assignment#1
116 lines
4.5 KiB
Swift
116 lines
4.5 KiB
Swift
import CocoaLumberjackSwift
|
|
|
|
public extension NSManagedObjectContext {
|
|
func wmf_create<T: NSManagedObject>(entityNamed entityName: String, withValue value: Any, forKey key: String) -> T? {
|
|
let object = NSEntityDescription.insertNewObject(forEntityName: entityName, into: self) as? T
|
|
object?.setValue(value, forKey: key)
|
|
return object
|
|
}
|
|
|
|
@discardableResult func wmf_create<T: NSManagedObject>(entityNamed entityName: String, withKeysAndValues dictionary: [String: Any?]) -> T? {
|
|
let object = NSEntityDescription.insertNewObject(forEntityName: entityName, into: self) as? T
|
|
for (key, value) in dictionary {
|
|
object?.setValue(value, forKey: key)
|
|
}
|
|
return object
|
|
}
|
|
|
|
|
|
func wmf_fetch<T: NSManagedObject>(objectForEntityName entityName: String, withValue value: Any, forKey key: String) -> T? {
|
|
let fetchRequest = NSFetchRequest<T>(entityName: entityName)
|
|
fetchRequest.predicate = NSPredicate(format: "\(key) == %@", argumentArray: [value])
|
|
fetchRequest.fetchLimit = 1
|
|
var results: [T] = []
|
|
do {
|
|
results = try fetch(fetchRequest)
|
|
} catch let error {
|
|
DDLogError("Error fetching: \(error)")
|
|
}
|
|
|
|
return results.first
|
|
}
|
|
|
|
func wmf_fetchOrCreate<T: NSManagedObject>(objectForEntityName entityName: String, withValue value: Any, forKey key: String) -> T? {
|
|
return wmf_fetch(objectForEntityName: entityName, withValue: value, forKey: key) ?? wmf_create(entityNamed: entityName, withValue: value, forKey: key)
|
|
}
|
|
|
|
func wmf_fetch<T: NSManagedObject, V: Hashable>(objectsForEntityName entityName: String, withValues values: [V], forKey key: String) throws -> [T]? {
|
|
let fetchRequest = NSFetchRequest<T>(entityName: entityName)
|
|
fetchRequest.predicate = NSPredicate(format: "\(key) IN %@", argumentArray: [values])
|
|
fetchRequest.fetchLimit = values.count
|
|
return try fetch(fetchRequest)
|
|
}
|
|
|
|
func wmf_fetchOrCreate<T: NSManagedObject, V: Hashable>(objectsForEntityName entityName: String, withValues values: [V], forKey key: String) throws -> [T]? {
|
|
var results = try wmf_fetch(objectsForEntityName: entityName, withValues: values, forKey: key) as? [T] ?? []
|
|
var missingValues = Set(values)
|
|
for result in results {
|
|
guard let value = result.value(forKey: key) as? V else {
|
|
continue
|
|
}
|
|
missingValues.remove(value)
|
|
}
|
|
for value in missingValues {
|
|
guard let object = wmf_create(entityNamed: entityName, withValue: value, forKey: key) as? T else {
|
|
continue
|
|
}
|
|
results.append(object)
|
|
}
|
|
return results
|
|
}
|
|
|
|
func wmf_batchProcessObjects<T: NSManagedObject>(matchingPredicate: NSPredicate? = nil, resetAfterSave: Bool = false, handler: (T) throws -> Void) throws {
|
|
let fetchRequest = T.fetchRequest()
|
|
let batchSize = 500
|
|
fetchRequest.predicate = matchingPredicate
|
|
fetchRequest.fetchBatchSize = batchSize
|
|
let results = try fetch(fetchRequest)
|
|
|
|
for (index, result) in results.enumerated() {
|
|
if let result = result as? T {
|
|
try handler(result)
|
|
}
|
|
let count = index + 1
|
|
if count % batchSize == 0 || count == results.count {
|
|
if hasChanges {
|
|
try save()
|
|
}
|
|
if resetAfterSave {
|
|
reset()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func wmf_batchProcess<T: NSManagedObject>(matchingPredicate: NSPredicate? = nil, resetAfterSave: Bool = false, handler: ([T]) throws -> Void) throws {
|
|
let fetchRequest = T.fetchRequest()
|
|
let batchSize = 500
|
|
fetchRequest.predicate = matchingPredicate
|
|
fetchRequest.fetchBatchSize = batchSize
|
|
let results = try fetch(fetchRequest) as? [T] ?? []
|
|
|
|
var start: Int = 0
|
|
var end: Int = 0
|
|
while start < results.count {
|
|
end = min(start + batchSize, results.count)
|
|
try handler([T](results[start..<end]))
|
|
if hasChanges {
|
|
try save()
|
|
}
|
|
if resetAfterSave {
|
|
reset()
|
|
}
|
|
start = end
|
|
}
|
|
}
|
|
|
|
func performWaitAndReturn<T>(_ block: () -> T?) -> T? {
|
|
var result: T? = nil
|
|
performAndWait {
|
|
result = block()
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|