Complete Challenge 3
> Modify the predicate string parameter to be an enum such as .beginsWith, then make that enum get resolved to a string inside the initializer.
This commit is contained in:
parent
241e97cf17
commit
b42f48bc19
|
@ -33,6 +33,7 @@
|
|||
F36B22BE2387EFE6000C9E74 /* DynamicFilteringExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36B22BD2387EFE6000C9E74 /* DynamicFilteringExample.swift */; };
|
||||
F36B22C22387F02D000C9E74 /* GenericFilteredListExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36B22C12387F02D000C9E74 /* GenericFilteredListExample.swift */; };
|
||||
F36B22C42388010F000C9E74 /* Country+FetchHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36B22C32388010F000C9E74 /* Country+FetchHelpers.swift */; };
|
||||
F36B22C723880CC0000C9E74 /* NSComparisonPredicate+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36B22C623880CC0000C9E74 /* NSComparisonPredicate+Utils.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -64,6 +65,7 @@
|
|||
F36B22BD2387EFE6000C9E74 /* DynamicFilteringExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicFilteringExample.swift; sourceTree = "<group>"; };
|
||||
F36B22C12387F02D000C9E74 /* GenericFilteredListExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GenericFilteredListExample.swift; sourceTree = "<group>"; };
|
||||
F36B22C32388010F000C9E74 /* Country+FetchHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Country+FetchHelpers.swift"; sourceTree = "<group>"; };
|
||||
F36B22C623880CC0000C9E74 /* NSComparisonPredicate+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSComparisonPredicate+Utils.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -203,6 +205,7 @@
|
|||
F36B22A2238783F5000C9E74 /* Reusables */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F36B22C523880C7A000C9E74 /* Predicate Utils */,
|
||||
F36B22A3238783FB000C9E74 /* Views */,
|
||||
);
|
||||
path = Reusables;
|
||||
|
@ -247,6 +250,14 @@
|
|||
path = Candy;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F36B22C523880C7A000C9E74 /* Predicate Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F36B22C623880CC0000C9E74 /* NSComparisonPredicate+Utils.swift */,
|
||||
);
|
||||
path = "Predicate Utils";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -334,6 +345,7 @@
|
|||
F36B229223869A44000C9E74 /* DynamicFilteringExampleListView.swift in Sources */,
|
||||
F36B22B42387E301000C9E74 /* Candy+CoreDataProperties.swift in Sources */,
|
||||
F36B22AA2387DE7D000C9E74 /* CandyListSection.swift in Sources */,
|
||||
F36B22C723880CC0000C9E74 /* NSComparisonPredicate+Utils.swift in Sources */,
|
||||
F316C3E72384994E00741AEC /* SceneDelegate.swift in Sources */,
|
||||
F316C3EA2384994E00741AEC /* ExploringCoreData.xcdatamodeld in Sources */,
|
||||
F36B22BE2387EFE6000C9E74 /* DynamicFilteringExample.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// PredicateComparison.swift
|
||||
// ExploringCoreData
|
||||
//
|
||||
// Created by CypherPoet on 11/22/19.
|
||||
// ✌️
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
extension NSComparisonPredicate {
|
||||
|
||||
|
||||
/// If applicable, makes a string consisting of braces and any characters for operator sensitivity.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - diacriticSensitive: [Diacritic sensitivity](https://en.wikipedia.org/wiki/Diacritic)
|
||||
/// refers to any possible glyphs that might be added to
|
||||
/// a chracter, such as accents or dots.
|
||||
static func operatorBraces(
|
||||
caseSensitive: Bool,
|
||||
diacriticSensitive: Bool
|
||||
) -> String? {
|
||||
guard caseSensitive || diacriticSensitive else { return nil }
|
||||
|
||||
return "[\(caseSensitive ? "c" : "")\(diacriticSensitive ? "d" : "")]"
|
||||
}
|
||||
|
||||
|
||||
/// The keyword to use within an NSPredicate expression
|
||||
public static func keyword(
|
||||
for predicateOperator: Operator
|
||||
) -> String {
|
||||
switch predicateOperator {
|
||||
case .lessThan:
|
||||
return "<"
|
||||
case .lessThanOrEqualTo:
|
||||
return "<="
|
||||
case .greaterThan:
|
||||
return ">"
|
||||
case .greaterThanOrEqualTo:
|
||||
return ">="
|
||||
case .equalTo:
|
||||
return "="
|
||||
case .notEqualTo:
|
||||
return "!="
|
||||
case .matches:
|
||||
return "MATCHES"
|
||||
case .like:
|
||||
return "LIKE"
|
||||
case .beginsWith:
|
||||
return "BEGINSWITH"
|
||||
case .endsWith:
|
||||
return "ENDSWITH"
|
||||
case .in:
|
||||
return "IN"
|
||||
case .customSelector:
|
||||
return "CUSTOMSELECTOR"
|
||||
case .contains:
|
||||
return "CONTAINS"
|
||||
case .between:
|
||||
return "BETWEEN"
|
||||
@unknown default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static func stringValue(
|
||||
for predicateOperator: Operator,
|
||||
caseSensitive: Bool = true,
|
||||
diacriticSensitive: Bool = true
|
||||
) -> String {
|
||||
let braces = Self.operatorBraces(
|
||||
caseSensitive: caseSensitive,
|
||||
diacriticSensitive: diacriticSensitive
|
||||
)
|
||||
|
||||
return "\(Self.keyword(for: predicateOperator))\(braces ?? "")"
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ struct FilteredList<ManagedObject: NSManagedObject, Content: View>: View {
|
|||
|
||||
/// The name of the [string comparison](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html)
|
||||
/// to be used between the `filterKey` and `filterValue`
|
||||
private var filterComparison: String
|
||||
private var comparisonOperator: NSComparisonPredicate.Operator
|
||||
|
||||
private var sortDescriptors: [NSSortDescriptor]
|
||||
|
||||
|
@ -27,21 +27,22 @@ struct FilteredList<ManagedObject: NSManagedObject, Content: View>: View {
|
|||
init(
|
||||
filterKey: String,
|
||||
filterValue: String,
|
||||
filterComparison: String = "BEGINSWITH",
|
||||
filterComparison comparisonOperator: NSComparisonPredicate.Operator = .beginsWith,
|
||||
sortDescriptors: [NSSortDescriptor] = [],
|
||||
@ViewBuilder buildListItem: @escaping (ManagedObject) -> Content
|
||||
) {
|
||||
self.filterKey = filterKey
|
||||
self.filterValue = filterValue
|
||||
self.filterComparison = filterComparison
|
||||
self.comparisonOperator = comparisonOperator
|
||||
self.sortDescriptors = sortDescriptors
|
||||
self.buildListItem = buildListItem
|
||||
|
||||
// 🤔 Lots of potential to make this even moar configurable, IMO
|
||||
let comparisonString = NSComparisonPredicate.stringValue(for: comparisonOperator)
|
||||
|
||||
self.fetchRequest = .init(
|
||||
entity: ManagedObject.entity(),
|
||||
sortDescriptors: sortDescriptors,
|
||||
predicate: NSPredicate(format: "%K \(filterComparison) %@", filterKey, filterValue),
|
||||
predicate: NSPredicate(format: "%K \(comparisonString) %@", filterKey, filterValue),
|
||||
animation: nil
|
||||
)
|
||||
}
|
||||
|
@ -61,19 +62,6 @@ extension FilteredList {
|
|||
}
|
||||
|
||||
|
||||
// MARK: - Computeds
|
||||
extension FilteredList {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: - View Variables
|
||||
extension FilteredList {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//// MARK: - Preview
|
||||
|
|
|
@ -29,10 +29,6 @@ extension OneToManyRelationshipsExample {
|
|||
}
|
||||
|
||||
|
||||
// MARK: - Computeds
|
||||
extension OneToManyRelationshipsExample {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - View Variables
|
||||
extension OneToManyRelationshipsExample {
|
||||
|
@ -41,6 +37,7 @@ extension OneToManyRelationshipsExample {
|
|||
FilteredList(
|
||||
filterKey: "name",
|
||||
filterValue: "U",
|
||||
filterComparison: .beginsWith,
|
||||
sortDescriptors: [
|
||||
Country.SortDescriptor.byAbbreviation,
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue