Skip to content

Commit

Permalink
🎨 Improve code formatting and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ftchirou committed Nov 26, 2020
1 parent 861089f commit 04d61c6
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 44 deletions.
2 changes: 1 addition & 1 deletion PredicateKit/CoreData/NSFetchRequestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ extension Query: NSExpressionConvertible {

// MARK: - KeyPath

internal extension AnyKeyPath {
extension AnyKeyPath {
var stringValue: String {
// https://github.com/apple/swift/blob/main/stdlib/public/core/KeyPath.swift#L124
guard let value = _kvcKeyPathString else {
Expand Down
24 changes: 17 additions & 7 deletions PredicateKit/CoreData/NSManagedObjectContextExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,9 @@ public struct FetchRequest<Entity: NSManagedObject> {
///
public func count() throws -> Int {
let request: NSFetchRequest<Entity> = requestBuilder.makeRequest(from: self)
#if DEBUG
debugInspector?.inspect(request.copy() as! NSFetchRequest<NSDictionary>)
#endif
return try context.count(for: request)
}

Expand Down Expand Up @@ -395,7 +398,7 @@ public struct FetchRequest<Entity: NSManagedObject> {
/// - sectionNameKeyPath - A key path on resulting objects that returns the section name. This will be used to pre-compute the section information.
/// - cacheName - Pre-computed section info is cached persistently to a private file under this name. Cached sections are checked to see if the time stamp matches the store, but not if you have illegally mutated the readonly fetch request, predicate, or sort descriptor. Defaults to `nil`.
///
/// - Returns: A fetchedResultsController with objects of type `Entity` matching the criteria specified by the fetch request.
/// - Returns: An NSFetchedResultsController with objects of type `Entity` matching the criteria specified by the fetch request.
///
/// ## Example
///
Expand All @@ -404,17 +407,24 @@ public struct FetchRequest<Entity: NSManagedObject> {
/// .sorted(by: \.creationDate, .descending)
/// .fetchedResultsController(sectionNameKeyPath: \.creationDate)
///
public func fetchedResultsController<T: Comparable & Primitive>(sectionNameKeyPath: KeyPath<Entity, T>, cacheName: String? = nil) -> NSFetchedResultsController<Entity> {
public func fetchedResultsController<T: Comparable & Primitive>(
sectionNameKeyPath: KeyPath<Entity, T>,
cacheName: String? = nil
) -> NSFetchedResultsController<Entity> {
fetchedResultsController(sectionNameKeyPath: sectionNameKeyPath.stringValue, cacheName: cacheName)
}

private func fetchedResultsController(sectionNameKeyPath: String?, cacheName: String? = nil) -> NSFetchedResultsController<Entity> {
private func fetchedResultsController(
sectionNameKeyPath: String?,
cacheName: String? = nil
) -> NSFetchedResultsController<Entity> {
let request: NSFetchRequest<Entity> = requestBuilder.makeRequest(from: self)
request.resultType = .managedObjectResultType
return NSFetchedResultsController(fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: sectionNameKeyPath,
cacheName: cacheName
return NSFetchedResultsController(
fetchRequest: request,
managedObjectContext: context,
sectionNameKeyPath: sectionNameKeyPath,
cacheName: cacheName
)
}

Expand Down
18 changes: 9 additions & 9 deletions PredicateKitTests/CoreDataTests/NSFetchRequestBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ final class NSFetchRequestBuilderTests: XCTestCase {
func testLessThanPredicate() throws {
let request = makeRequest(\Data.count < 42)
let builder = makeRequestBuilder()

let result: NSFetchRequest<Data> = builder.makeRequest(from: request)

let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.leftExpression, NSExpression(forKeyPath: "count"))
XCTAssertEqual(comparison.rightExpression, NSExpression(forConstantValue: 42))
Expand All @@ -50,13 +50,13 @@ final class NSFetchRequestBuilderTests: XCTestCase {
let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.predicateFormat, NSPredicate(format: "relationships[FIRST].count <[c] 42").predicateFormat)
}

func testLessThanOrEqualPredicate() throws {
let request = makeRequest(\Data.count <= 42)
let builder = makeRequestBuilder()

let result: NSFetchRequest<Data> = builder.makeRequest(from: request)

let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.leftExpression, NSExpression(forKeyPath: "count"))
XCTAssertEqual(comparison.rightExpression, NSExpression(forConstantValue: 42))
Expand Down Expand Up @@ -96,7 +96,7 @@ final class NSFetchRequestBuilderTests: XCTestCase {
let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.predicateFormat, NSPredicate(format: "relationships[LAST].count ==[c] 42").predicateFormat)
}

func testNotEqualPredicate() throws {
let request = makeRequest(\Data.text != "Hello, World!")
let builder = makeRequestBuilder()
Expand All @@ -109,7 +109,7 @@ final class NSFetchRequestBuilderTests: XCTestCase {
XCTAssertEqual(comparison.predicateOperatorType, .notEqualTo)
XCTAssertEqual(comparison.comparisonPredicateModifier, .direct)
}

func testArrayElementNotEqualPredicate() throws {
let request = makeRequest((\Data.relationships).last(\.count) != 42)
let builder = makeRequestBuilder()
Expand All @@ -119,7 +119,7 @@ final class NSFetchRequestBuilderTests: XCTestCase {
let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.predicateFormat, NSPredicate(format: "relationships[LAST].count !=[c] 42").predicateFormat)
}

func testGreaterThanOrEqualPredicate() throws {
let request = makeRequest(\Data.count >= 42)
let builder = makeRequestBuilder()
Expand All @@ -142,7 +142,7 @@ final class NSFetchRequestBuilderTests: XCTestCase {
let comparison = try XCTUnwrap(result.predicate as? NSComparisonPredicate)
XCTAssertEqual(comparison.predicateFormat, NSPredicate(format: "relationships[3].count >=[c] 42").predicateFormat)
}

func testGreaterThanPredicate() throws {
let request = makeRequest(\Data.count > 42)
let builder = makeRequestBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ final class NSManagedObjectContextExtensionsTests: XCTestCase {
override func tearDown() {
super.tearDown()
container.viewContext.deleteAll(Note.self)
container.viewContext.deleteAll(User.self)
container.viewContext.deleteAll(UserAccount.self)
container.viewContext.deleteAll(Profile.self)
container.viewContext.deleteAll(BillingInfo.self)
container = nil
}

Expand Down Expand Up @@ -260,7 +264,7 @@ final class NSManagedObjectContextExtensionsTests: XCTestCase {
XCTAssertEqual(notes.first?.numberOfViews, 3)
}

func testFetchWithPredicateOnAirstArrayElement() throws {
func testFetchWithPredicateOnFirstArrayElement() throws {
try container.viewContext.insertNotes(
(text: "Hello, World!", creationDate: Date(), numberOfViews: 42, tags: ["greeting", "casual"]),
(text: "Goodbye!", creationDate: Date(), numberOfViews: 3, tags: ["casual", "greeting"])
Expand Down Expand Up @@ -585,11 +589,9 @@ final class NSManagedObjectContextExtensionsTests: XCTestCase {
.fetchedResultsController()

try controller.performFetch()
let sectionCount = controller.sections?.count
let itemCount = controller.sections?.first?.numberOfObjects

XCTAssertEqual(sectionCount, 1)
XCTAssertEqual(itemCount, 2)
XCTAssertNil(controller.sectionNameKeyPath)
XCTAssertEqual(controller.sections?.count, 1)
XCTAssertEqual(controller.sections?.first?.numberOfObjects, 2)
}

func testFetchedResultsControllerSections() throws {
Expand All @@ -610,14 +612,10 @@ final class NSManagedObjectContextExtensionsTests: XCTestCase {

let sectionCount = controller.sections?.count
XCTAssertEqual(sectionCount, 3)

let itemCount0 = controller.sections?[0].numberOfObjects
let itemCount1 = controller.sections?[1].numberOfObjects
let itemCount2 = controller.sections?[2].numberOfObjects

XCTAssertEqual(itemCount0, 1)
XCTAssertEqual(itemCount1, 2)
XCTAssertEqual(itemCount2, 1)
XCTAssertEqual(controller.sections?[0].numberOfObjects, 1)
XCTAssertEqual(controller.sections?[1].numberOfObjects, 2)
XCTAssertEqual(controller.sections?[2].numberOfObjects, 1)
XCTAssertEqual(controller.sectionNameKeyPath, "creationDate")
}

func testNSFetchRequestsAreForwardedToInspector() throws {
Expand Down
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ comparisons and logical operators, literal values, and functions.
- [Quick start](#quick-start)
- [Fetching objects](#fetching-objects)
- [Configuring the fetch](#configuring-the-fetch)
- [Fetching objects with an NSFetchedResultsController](#fetching-objects-with-an-nsfetchedresultscontroller)
- [Counting objects](#counting-objects)
- [Documentation](#documentation)
- [Writing predicates](#writing-predicates)
Expand Down Expand Up @@ -135,19 +136,6 @@ let notes: [[String: Any]] = try managedObjectContext
.result()
```

### Fetching objects with an NSFetchedResultsController

Instead of directly fetching results, you can use `fetchedResultsController()` to instantiate an NSFetchedResultsController with the configured fetch. `fetchedResultsController` has two optional parameters: `sectionNameKeyPath` is a KeyPath on the returned objects used to compute section info and `cacheName` is the name of a file to store pre-computed section info.

###### Example

```swift
let controller: NSFetchedResultsController<Note> = managedObjectContext
.fetch(where: \Note.text == "Hello, World!" && \Note.creationDate < Date())
.sorted(by: \Note.creationDate, .descending)
.fetchedResultsController(sectionNameKeyPath: \Note.creationDate)
```

## Configuring the fetch

`fetch(where:)` returns an object of type `FetchRequest`. You can apply a series of modifiers on this object to further configure how the objects should be matched and returned.
Expand All @@ -167,6 +155,19 @@ let notes: [Note] = try managedObjectContext

See [Request modifiers](#request-modifiers) for more about modifiers.

## Fetching objects with an NSFetchedResultsController

Instead of directly fetching results, you can use `fetchedResultsController()` to instantiate an `NSFetchedResultsController` with the configured fetch. `fetchedResultsController` has two optional parameters: `sectionNameKeyPath` is a [key-path](https://developer.apple.com/documentation/swift/keypath) on the returned objects used to compute section info and `cacheName` is the name of a file to store pre-computed section info.

###### Example

```swift
let controller: NSFetchedResultsController<Note> = managedObjectContext
.fetch(where: \Note.text == "Hello, World!" && \Note.creationDate < Date())
.sorted(by: \Note.creationDate, .descending)
.fetchedResultsController(sectionNameKeyPath: \Note.creationDate)
```

## Counting objects

To count the number of objects matching a predicate, use the function `count(where:)` on an instance of `NSManagedObjectContext`.
Expand Down

0 comments on commit 04d61c6

Please sign in to comment.