Skip to content

Instantly share code, notes, and snippets.

@shakemno
Forked from tadija/AECoreData.swift
Created December 9, 2019 21:50
Show Gist options
  • Select an option

  • Save shakemno/9786bd6bd0319b4ee96c372dab681f2b to your computer and use it in GitHub Desktop.

Select an option

Save shakemno/9786bd6bd0319b4ee96c372dab681f2b to your computer and use it in GitHub Desktop.
AECoreData
/**
* https://gist.github.com/tadija/6003830264d67a87193ff0c3d20373e7
* Copyright (c) Marko Tadić 2018
* Licensed under the MIT license. See LICENSE file.
*/
import CoreData
extension NSFetchRequestResult where Self: NSManagedObject {
// MARK: Queries
public static func findOrCreate(with predicate: NSPredicate? = nil, in context: NSManagedObjectContext) -> Self {
return find(with: predicate, in: context) ?? self.init(context: context)
}
public static func find(key: String, value: Any, in context: NSManagedObjectContext?) -> Self? {
return find(with: predicate(key: key, value: value), in: context)
}
public static func find(with predicate: NSPredicate? = nil, in context: NSManagedObjectContext?) -> Self? {
if let objectFromMemory = context?.registeredObjects.first(where: {
let isFulfilled = !$0.isFault
let matchesPredicate = predicate?.evaluate(with: $0 as? Self) ?? false
return isFulfilled && matchesPredicate
}) as? Self {
/// - Note: object is already in memory, this is way more performant than making a fetch request
return objectFromMemory
} else {
return all(with: predicate, limit: 1, in: context).first
}
}
public static func incrementedInteger(for attribute: String, in context: NSManagedObjectContext?) -> Int {
let sortDescriptor = NSSortDescriptor(key: attribute, ascending: false)
guard
let object = all(orderedBy: [sortDescriptor], limit: 1, in: context).first,
let max = object.value(forKey: attribute) as? Int
else { return 0 }
return max + 1
}
public static func all(with predicate: NSPredicate? = nil,
orderedBy sortDescriptors: [NSSortDescriptor] = [],
limit: Int? = nil,
in context: NSManagedObjectContext?) -> [Self] {
guard let context = context
else { return [] }
let request = fetchRequest(predicate: predicate, sortDescriptors: sortDescriptors, limit: limit)
let result = try? fetch(request, in: context)
return result ?? []
}
public static func unmanaged() -> Self {
return self.init(entity: self.entity(), insertInto: nil)
}
public func `in`(_ context: NSManagedObjectContext?) -> Self? {
guard let context = context, let object = context.object(with: objectID) as? Self else {
return nil
}
return object
}
// MARK: Predicate & Fetch Request
public static func predicate(key: String, value: Any) -> NSPredicate {
return NSPredicate(format: "%K = %@", argumentArray: [key, value])
}
public static func predicate(attributes: [String: Any],
type: NSCompoundPredicate.LogicalType = .and) -> NSPredicate {
let predicates = attributes.map { predicate(key: $0.key, value: $0.value) }
let compoundPredicate = NSCompoundPredicate(type: type, subpredicates: predicates)
return compoundPredicate
}
public static func fetchRequest(predicate: NSPredicate? = nil, sortDescriptors: [NSSortDescriptor] = [],
limit: Int? = nil, offset: Int? = nil, batchSize: Int? = nil,
relationshipKeyPathsForPrefetching: [String] = []) -> NSFetchRequest<Self> {
let request = NSFetchRequest<Self>(entityName: String(describing: Self.self))
request.predicate = predicate
request.sortDescriptors = sortDescriptors
request.fetchLimit = limit ?? request.fetchLimit
request.fetchOffset = offset ?? request.fetchOffset
request.fetchBatchSize = batchSize ?? request.fetchBatchSize
request.relationshipKeyPathsForPrefetching = relationshipKeyPathsForPrefetching
return request
}
public static func fetch(_ request: NSFetchRequest<Self> = fetchRequest(),
in context: NSManagedObjectContext) throws -> [Self] {
return try context.fetch(request)
}
// MARK: Batch Update & Delete
@discardableResult
public static func batchUpdate(properties: [String: Any], predicate: NSPredicate? = nil,
resultType: NSBatchUpdateRequestResultType = .updatedObjectsCountResultType,
in context: NSManagedObjectContext) -> NSBatchUpdateResult? {
let request = NSBatchUpdateRequest(entityName: String(describing: Self.self))
request.propertiesToUpdate = properties
request.predicate = predicate
request.resultType = resultType
do {
let result = try context.execute(request)
return result as? NSBatchUpdateResult
} catch {
return nil
}
}
@discardableResult
public static func batchDelete(with predicate: NSPredicate? = nil,
resultType: NSBatchDeleteRequestResultType = .resultTypeCount,
in context: NSManagedObjectContext) -> NSBatchDeleteResult? {
guard let request = fetchRequest(predicate: predicate) as? NSFetchRequest<NSFetchRequestResult>
else { return nil }
let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
deleteRequest.resultType = resultType
do {
let result = try context.execute(deleteRequest)
return result as? NSBatchDeleteResult
} catch {
return nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment