forked from objcio/core-data
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathManagedObject.swift
141 lines (110 loc) · 5.09 KB
/
ManagedObject.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//
// ManagedObject.swift
// Moody
//
// Created by Florian on 29/05/15.
// Copyright (c) 2015 objc.io. All rights reserved.
//
import CoreData
public class ManagedObject: NSManagedObject {
}
public protocol ManagedObjectType: class {
static var entityName: String { get }
static var defaultSortDescriptors: [NSSortDescriptor] { get }
static var defaultPredicate: NSPredicate { get }
var managedObjectContext: NSManagedObjectContext? { get }
}
public protocol DefaultManagedObjectType: ManagedObjectType {}
extension DefaultManagedObjectType {
public static var defaultPredicate: NSPredicate { return NSPredicate(value: true) }
}
extension ManagedObjectType {
public static var defaultSortDescriptors: [NSSortDescriptor] {
return []
}
public static var sortedFetchRequest: NSFetchRequest {
let request = NSFetchRequest(entityName: entityName)
request.sortDescriptors = defaultSortDescriptors
request.predicate = defaultPredicate
return request
}
public static func sortedFetchRequestWithPredicate(predicate: NSPredicate) -> NSFetchRequest {
let request = sortedFetchRequest
guard let existingPredicate = request.predicate else { fatalError("must have predicate") }
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [existingPredicate, predicate])
return request
}
public static func sortedFetchRequestWithPredicateFormat(format: String, args: CVarArgType...) -> NSFetchRequest {
let predicate = withVaList(args) { NSPredicate(format: format, arguments: $0) }
return sortedFetchRequestWithPredicate(predicate)
}
public static func predicateWithFormat(format: String, args: CVarArgType...) -> NSPredicate {
let predicate = withVaList(args) { NSPredicate(format: format, arguments: $0) }
return predicateWithPredicate(predicate)
}
public static func predicateWithPredicate(predicate: NSPredicate) -> NSPredicate {
return NSCompoundPredicate(andPredicateWithSubpredicates: [defaultPredicate, predicate])
}
}
extension ManagedObjectType where Self: ManagedObject {
public static func findOrCreateInContext(moc: NSManagedObjectContext, matchingPredicate predicate: NSPredicate, configure: Self -> ()) -> Self {
guard let obj = findOrFetchInContext(moc, matchingPredicate: predicate) else {
let newObject: Self = moc.insertObject()
configure(newObject)
return newObject
}
return obj
}
public static func findOrFetchInContext(moc: NSManagedObjectContext, matchingPredicate predicate: NSPredicate) -> Self? {
guard let obj = materializedObjectInContext(moc, matchingPredicate: predicate) else {
return fetchInContext(moc) { request in
request.predicate = predicate
request.returnsObjectsAsFaults = false
request.fetchLimit = 1
}.first
}
return obj
}
public static func fetchInContext(context: NSManagedObjectContext, @noescape configurationBlock: NSFetchRequest -> () = { _ in }) -> [Self] {
let request = NSFetchRequest(entityName: Self.entityName)
configurationBlock(request)
guard let result = try! context.executeFetchRequest(request) as? [Self] else { fatalError("Fetched objects have wrong type") }
return result
}
public static func countInContext(context: NSManagedObjectContext, @noescape configurationBlock: NSFetchRequest -> () = { _ in }) -> Int {
let request = NSFetchRequest(entityName: entityName)
configurationBlock(request)
var error: NSError?
let result = context.countForFetchRequest(request, error: &error)
guard result != NSNotFound else { fatalError("Failed to execute fetch request: \(error)") }
return result
}
public static func materializedObjectInContext(moc: NSManagedObjectContext, matchingPredicate predicate: NSPredicate) -> Self? {
for obj in moc.registeredObjects where !obj.fault {
guard let res = obj as? Self where predicate.evaluateWithObject(res) else { continue }
return res
}
return nil
}
}
extension ManagedObjectType where Self: ManagedObject {
public static func fetchSingleObjectInContext(moc: NSManagedObjectContext, cacheKey: String, configure: NSFetchRequest -> ()) -> Self? {
guard let cached = moc.objectForSingleObjectCacheKey(cacheKey) as? Self else {
let result = fetchSingleObjectInContext(moc, configure: configure)
moc.setObject(result, forSingleObjectCacheKey: cacheKey)
return result
}
return cached
}
private static func fetchSingleObjectInContext(moc: NSManagedObjectContext, configure: NSFetchRequest -> ()) -> Self? {
let result = fetchInContext(moc) { request in
configure(request)
request.fetchLimit = 2
}
switch result.count {
case 0: return nil
case 1: return result[0]
default: fatalError("Returned multiple objects, expected max 1")
}
}
}