Skip to content

Commit 7d081a6

Browse files
authored
Replace NSPredicate with Predicate (#107)
1 parent 57d0bb3 commit 7d081a6

21 files changed

+211
-211
lines changed

OpenStack Summit/CoreSummit/CoreDataDecodable.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,29 @@ public extension NSManagedObjectContext {
3434
}
3535

3636
@inline(__always)
37-
func managedObjects<T: CoreDataDecodable>(_ decodableType: T.Type, predicate: NSPredicate? = nil, sortDescriptors: [NSSortDescriptor] = [], limit: Int = 0) throws -> [T] {
37+
func managedObjects<T: CoreDataDecodable>(_ decodableType: T.Type,
38+
predicate: NSPredicate? = nil,
39+
sortDescriptors: [NSSortDescriptor] = [],
40+
limit: Int = 0) throws -> [T] {
3841

39-
let results = try self.managedObjects(decodableType.ManagedObject.self, predicate: predicate, sortDescriptors: sortDescriptors, limit: limit)
42+
let results = try self.managedObjects(decodableType.ManagedObject.self,
43+
predicate: predicate,
44+
sortDescriptors: sortDescriptors,
45+
limit: limit)
4046

4147
return T.from(managedObjects: results)
4248
}
4349

4450
@inline(__always)
45-
func managedObjects<T: CoreDataDecodable>(_ decodableType: T.Type, predicate: Predicate, sortDescriptors: [NSSortDescriptor] = []) throws -> [T] {
51+
func managedObjects<T: CoreDataDecodable>(_ decodableType: T.Type,
52+
predicate: Predicate,
53+
sortDescriptors: [NSSortDescriptor] = [],
54+
limit: Int = 0) throws -> [T] {
4655

47-
let results = try self.managedObjects(decodableType.ManagedObject.self, predicate: predicate, sortDescriptors: sortDescriptors)
56+
let results = try self.managedObjects(decodableType.ManagedObject.self,
57+
predicate: predicate.toFoundation(),
58+
sortDescriptors: sortDescriptors,
59+
limit: limit)
4860

4961
return T.from(managedObjects: results)
5062
}
@@ -83,7 +95,7 @@ public extension NSFetchedResultsController {
8395
public func NSFetchedResultsController <T: CoreDataDecodable>
8496
(_ decodable: T.Type,
8597
delegate: NSFetchedResultsControllerDelegate? = nil,
86-
predicate: NSPredicate? = nil,
98+
predicate: Predicate? = nil,
8799
sortDescriptors: [NSSortDescriptor] = [],
88100
sectionNameKeyPath: String? = nil,
89101
context: NSManagedObjectContext) -> NSFetchedResultsController<T.ManagedObject> {
@@ -94,7 +106,7 @@ public func NSFetchedResultsController <T: CoreDataDecodable>
94106

95107
let fetchRequest = NSFetchRequest<T.ManagedObject>(entityName: entity.name!)
96108

97-
fetchRequest.predicate = predicate
109+
fetchRequest.predicate = predicate?.toFoundation()
98110

99111
fetchRequest.sortDescriptors = sortDescriptors
100112

OpenStack Summit/CoreSummit/EventManagedObject.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public final class EventManagedObject: Entity {
5555
@NSManaged public var groups: Set<GroupManagedObject>
5656

5757
@NSManaged public var summit: SummitManagedObject
58+
59+
// MARK: - Inverse Relationhips
60+
61+
@NSManaged public var attendees: Set<AttendeeManagedObject>
5862
}
5963

6064
// MARK: - Encoding
@@ -178,6 +182,7 @@ public extension EventManagedObject {
178182

179183
//let predicate = NSPredicate(format: "name CONTAINS [c] %@ or ANY presentation.speakers.firstName CONTAINS [c] %@ or ANY presentation.speakers.lastName CONTAINS [c] %@ or presentation.level CONTAINS [c] %@ or ANY tags.name CONTAINS [c] %@ or eventType.name CONTAINS [c] %@", searchTerm, searchTerm, searchTerm, searchTerm, searchTerm, searchTerm)
180184
let predicate: Predicate = (#keyPath(EventManagedObject.name)).compare(.contains, [.caseInsensitive], value)
185+
|| (#keyPath(EventManagedObject.presentation.speakers.firstName)).compare(.any, .contains, [.caseInsensitive], value)
181186
|| (#keyPath(EventManagedObject.presentation.speakers.lastName)).compare(.any, .contains, [.caseInsensitive], value)
182187
|| (#keyPath(EventManagedObject.presentation.level)).compare(.contains, [.caseInsensitive], value)
183188
|| (#keyPath(EventManagedObject.tags.name)).compare(.any, .contains, [.caseInsensitive], value)
@@ -259,7 +264,7 @@ public extension EventManagedObject {
259264

260265
assert(predicates.count > 1)
261266

262-
return try context.managedObjects(EventManagedObject.self,
267+
return try context.managedObjects(self,
263268
predicate: .compound(.and(predicates)),
264269
sortDescriptors: sortDescriptors)
265270
}
@@ -273,7 +278,7 @@ public extension EventManagedObject {
273278
&& #keyPath(EventManagedObject.end) <= end
274279
&& #keyPath(EventManagedObject.summit.id) == summit
275280

276-
return try context.managedObjects(EventManagedObject.self, predicate: predicate, sortDescriptors: sortDescriptors)
281+
return try context.managedObjects(self, predicate: predicate, sortDescriptors: sortDescriptors)
277282
}
278283
}
279284

OpenStack Summit/CoreSummit/SpeakerManagedObject.swift

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -82,70 +82,11 @@ extension Speaker: CoreDataEncodable {
8282

8383
public extension SpeakerManagedObject {
8484

85-
public enum Property: String {
86-
87-
case id, firstName, lastName, addressBookSectionName, title, pictureURL, twitter, irc, biography, member
88-
}
89-
9085
static var sortDescriptors: [NSSortDescriptor] {
9186

92-
return [NSSortDescriptor(key: Property.addressBookSectionName.rawValue, ascending: true),
93-
NSSortDescriptor(key: Property.firstName.rawValue, ascending: true),
94-
NSSortDescriptor(key: Property.lastName.rawValue, ascending: true),
95-
NSSortDescriptor(key: Property.id.rawValue, ascending: true)]
96-
}
97-
}
98-
99-
public extension Speaker {
100-
101-
static func filter(_ searchTerm: String = "",
102-
page: Int, objectsPerPage: Int,
103-
summit: Identifier? = nil,
104-
context: NSManagedObjectContext) throws -> [Speaker] {
105-
106-
var predicates = [NSPredicate]()
107-
108-
if searchTerm.isEmpty == false {
109-
110-
let searchPredicate = NSPredicate(format: "firstName CONTAINS[c] %@ OR lastName CONTAINS[c] %@", searchTerm, searchTerm)
111-
112-
predicates.append(searchPredicate)
113-
}
114-
115-
if let summitID = summit,
116-
let summit = try SummitManagedObject.find(summitID, context: context) {
117-
118-
let summitPredicate = NSPredicate(format: "%@ IN summits", summit)
119-
120-
predicates.append(summitPredicate)
121-
}
122-
123-
let predicate: NSPredicate?
124-
125-
if predicates.count > 1 {
126-
127-
predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
128-
129-
} else {
130-
131-
predicate = predicates.first
132-
}
133-
134-
let results = try context.managedObjects(ManagedObject.self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
135-
136-
var speakers = [ManagedObject]()
137-
138-
let startRecord = (page - 1) * objectsPerPage
139-
140-
let endRecord = (startRecord + (objectsPerPage - 1)) <= results.count ? startRecord + (objectsPerPage - 1) : results.count - 1
141-
142-
if (startRecord <= endRecord) {
143-
144-
for index in (startRecord...endRecord) {
145-
speakers.append(results[index])
146-
}
147-
}
148-
149-
return Speaker.from(managedObjects: speakers)
87+
return [NSSortDescriptor(key: #keyPath(addressBookSectionName), ascending: true),
88+
NSSortDescriptor(key:#keyPath(SpeakerManagedObject.firstName), ascending: true),
89+
NSSortDescriptor(key:#keyPath(SpeakerManagedObject.lastName), ascending: true),
90+
NSSortDescriptor(key:#keyPath(SpeakerManagedObject.id), ascending: true)]
15091
}
15192
}

OpenStack Summit/CoreSummit/TagManagedObject.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Foundation
1010
import CoreData
11+
import Predicate
1112

1213
public final class TagManagedObject: Entity {
1314

@@ -53,10 +54,9 @@ public extension Tag {
5354

5455
static func search(_ searchTerm: String, context: NSManagedObjectContext) throws -> [Tag] {
5556

56-
let predicate = NSPredicate(format: "name CONTAINS[c] %@", searchTerm)
57+
//let predicate = NSPredicate(format: "name CONTAINS[c] %@", searchTerm)
58+
let predicate: Predicate = (#keyPath(TagManagedObject.name)).compare(.contains, [.caseInsensitive], .value(.string(searchTerm)))
5759

58-
let managedObjects = try context.managedObjects(ManagedObject.self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
59-
60-
return Tag.from(managedObjects: managedObjects)
60+
return try context.managedObjects(self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
6161
}
6262
}

OpenStack Summit/CoreSummit/TrackGroupManagedObject.swift

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Foundation
1010
import CoreData
11+
import Predicate
1112

1213
public final class TrackGroupManagedObject: Entity {
1314

@@ -18,6 +19,10 @@ public final class TrackGroupManagedObject: Entity {
1819
@NSManaged public var color: String
1920

2021
@NSManaged public var tracks: Set<TrackManagedObject>
22+
23+
// Inverse Relationships
24+
25+
@NSManaged public var summits: Set<SummitManagedObject>
2126
}
2227

2328
// MARK: - Encoding
@@ -57,7 +62,7 @@ public extension TrackGroupManagedObject {
5762

5863
static var sortDescriptors: [NSSortDescriptor] {
5964

60-
return [NSSortDescriptor(key: "name", ascending: true)]
65+
return [NSSortDescriptor(key: #keyPath(TrackGroupManagedObject.name), ascending: true)]
6166
}
6267
}
6368

@@ -66,15 +71,9 @@ public extension TrackGroup {
6671
/// Fetch all track groups that have some event associated with them.
6772
static func scheduled(for summit: Identifier, context: NSManagedObjectContext) throws -> [TrackGroup] {
6873

69-
guard let summitManagedObject = try SummitManagedObject.find(summit, context: context)
70-
else { return [] }
71-
72-
let events = try context.managedObjects(EventManagedObject.self, predicate: NSPredicate(format: "track != nil AND summit == %@", summitManagedObject))
73-
74-
var groups = events.reduce([TrackGroupManagedObject](), { $0.0 + Array($0.1.track!.groups) })
75-
76-
groups = (Set(groups) as NSSet).sortedArray(using: ManagedObject.sortDescriptors) as! [TrackGroupManagedObject]
74+
let predicate: Predicate = #keyPath(TrackGroupManagedObject.tracks.events) + ".@count" > 0
75+
&& (#keyPath(TrackGroupManagedObject.summits)).compare(.contains, .value(.int64(summit)))
7776

78-
return TrackGroup.from(managedObjects: groups)
77+
return try context.managedObjects(self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
7978
}
8079
}

OpenStack Summit/CoreSummit/TrackManagedObject.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Foundation
1010
import CoreData
11+
import Predicate
1112

1213
public final class TrackManagedObject: Entity {
1314

@@ -17,7 +18,9 @@ public final class TrackManagedObject: Entity {
1718

1819
// Inverse Relationships
1920

20-
@NSManaged public var presentations: Set<PresentationManagedObject>
21+
@NSManaged public var events: Set<EventManagedObject>
22+
23+
@NSManaged public var summits: Set<SummitManagedObject>
2124
}
2225

2326
// MARK: - Encoding
@@ -68,43 +71,43 @@ public extension TrackManagedObject {
6871

6972
static var sortDescriptors: [NSSortDescriptor] {
7073

71-
return [NSSortDescriptor(key: "name", ascending: true)]
74+
return [NSSortDescriptor(key: #keyPath(TrackManagedObject.name), ascending: true)]
7275
}
7376
}
7477

7578
public extension Track {
7679

7780
static func search(_ searchTerm: String, context: NSManagedObjectContext) throws -> [Track] {
7881

79-
let predicate = NSPredicate(format: "name CONTAINS[c] %@", searchTerm)
80-
81-
let managedObjects = try context.managedObjects(TrackManagedObject.self, predicate: predicate, sortDescriptors: TrackManagedObject.sortDescriptors)
82+
let predicate: Predicate = (#keyPath(TrackManagedObject.name)).compare(.contains, [.caseInsensitive], .value(.string(searchTerm)))
8283

83-
return Track.from(managedObjects: managedObjects)
84+
return try Track.filter(predicate,
85+
sort: ManagedObject.sortDescriptors,
86+
context: context)
8487
}
8588

8689
/// Get scheduled tracks that belong to track groups.
87-
static func `for`(groups trackGroups: [Identifier], context: NSManagedObjectContext) throws -> [Track] {
90+
static func `for`(groups trackGroups: [Identifier] = [], context: NSManagedObjectContext) throws -> [Track] {
8891

89-
let predicate: NSPredicate
92+
let predicate: Predicate
9093

91-
let scheduledTracksPredicate = NSPredicate(format: "events.@count > 0")
94+
// let scheduledTracksPredicate = Predicate(format: "events.@count > 0")
95+
let scheduledTracks: Predicate = #keyPath(TrackManagedObject.events) + ".@count" > 0
9296

9397
// optionally filter for track groups
9498
if trackGroups.isEmpty == false {
9599

96-
let trackGroupIdentifiers = trackGroups.map { NSNumber(value: Int64($0) as Int64) }
97-
98-
let trackGroupsPredicate = NSPredicate(format: "ANY groups.id IN %@", [trackGroupIdentifiers])
100+
//let trackGroupsPredicate = NSPredicate(format: "ANY groups.id IN %@", [trackGroups])
101+
let trackGroupsPredicate: Predicate = (#keyPath(TrackManagedObject.groups.id)).in(trackGroups)
99102

100-
predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [scheduledTracksPredicate, trackGroupsPredicate])
103+
predicate = .compound(.and([scheduledTracks, trackGroupsPredicate]))
101104

102105
} else {
103106

104-
predicate = scheduledTracksPredicate
107+
predicate = scheduledTracks
105108
}
106109

107-
return try context.managedObjects(Track.self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
110+
return try context.managedObjects(self, predicate: predicate, sortDescriptors: ManagedObject.sortDescriptors)
108111
}
109112
}
110113

OpenStack Summit/OpenStack Summit/Filter.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,14 @@ struct ScheduleFilter: Equatable {
9494

9595
// fetch data
9696
let trackGroups = try! TrackGroup.scheduled(for: summitID, context: context)
97-
let levels = try! Set(context.managedObjects(PresentationManagedObject.self, predicate: "event.summit.id" == summitID)
97+
let levels = try! Set(context.managedObjects(PresentationManagedObject.self, predicate: #keyPath(PresentationManagedObject.event.summit.id) == summitID)
9898
.flatMap { $0.level })
9999
.flatMap { Level(rawValue: $0) }
100100
.sorted()
101101

102-
let venues = try! context.managedObjects(Venue.self, predicate: NSPredicate(format: "summit == %@", summit), sortDescriptors: VenueManagedObject.sortDescriptors)
102+
let venues = try! context.managedObjects(Venue.self,
103+
predicate: #keyPath(VenueManagedObject.summit.id) == summitID,
104+
sortDescriptors: VenueManagedObject.sortDescriptors)
103105

104106
// populate filter categories
105107

OpenStack Summit/OpenStack Summit/GeneralScheduleFilterViewController.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import UIKit
1010
import Foundation
1111
import CoreSummit
12+
import Predicate
1213

1314
final class GeneralScheduleFilterViewController: UITableViewController {
1415

@@ -113,9 +114,10 @@ final class GeneralScheduleFilterViewController: UITableViewController {
113114
if let trackGroupsSection = scheduleFilter.allFilters[.trackGroup] {
114115

115116
// fetch from CoreData because it caches fetch request results and is more efficient
116-
let identifiers = trackGroupsSection.map { NSNumber(value: Int64(identifier(for: $0))) }
117+
let identifiers = trackGroupsSection.map { identifier(for: $0) }
117118

118-
let predicate = NSPredicate(format: "id IN %@", identifiers)
119+
//let predicate = NSPredicate(format: "id IN %@", identifiers)
120+
let predicate: Predicate = (#keyPath(TrackGroupManagedObject.id)).in(identifiers)
119121

120122
let trackGroups = try! context.managedObjects(TrackGroup.self, predicate: predicate, sortDescriptors: TrackGroup.ManagedObject.sortDescriptors)
121123

@@ -134,9 +136,10 @@ final class GeneralScheduleFilterViewController: UITableViewController {
134136
if let venuesSection = scheduleFilter.allFilters[.venue] {
135137

136138
// fetch from CoreData because it caches fetch request results and is more efficient
137-
let identifiers = venuesSection.map { NSNumber(value: Int64(identifier(for: $0))) }
139+
let identifiers = venuesSection.map { identifier(for: $0) }
138140

139-
let predicate = NSPredicate(format: "id IN %@", identifiers)
141+
//let predicate = NSPredicate(format: "id IN %@", identifiers)
142+
let predicate: Predicate = (#keyPath(VenueManagedObject.id)).in(identifiers)
140143

141144
let venues = try! context.managedObjects(Venue.self, predicate: predicate, sortDescriptors: Venue.ManagedObject.sortDescriptors)
142145

0 commit comments

Comments
 (0)