Skip to content

Commit 3f4cd8e

Browse files
authored
Refactor structure (#8)
1. `ManagedObjectFindOrCreateBy` has been split into `ManagedObjectFindOrCreateBy` and `ManagedObjectFind`. 2. Updated documentation and repo structure
1 parent fb70830 commit 3f4cd8e

20 files changed

+156
-141
lines changed

Example App/Example App.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@
314314
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
315315
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
316316
CODE_SIGN_STYLE = Automatic;
317-
CURRENT_PROJECT_VERSION = 1;
317+
CURRENT_PROJECT_VERSION = 2;
318318
DEVELOPMENT_ASSET_PATHS = "\"Example App/Preview Content\"";
319319
DEVELOPMENT_TEAM = 63P2N3D9XL;
320320
ENABLE_PREVIEWS = YES;
@@ -344,7 +344,7 @@
344344
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
345345
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
346346
CODE_SIGN_STYLE = Automatic;
347-
CURRENT_PROJECT_VERSION = 1;
347+
CURRENT_PROJECT_VERSION = 2;
348348
DEVELOPMENT_ASSET_PATHS = "\"Example App/Preview Content\"";
349349
DEVELOPMENT_TEAM = 63P2N3D9XL;
350350
ENABLE_PREVIEWS = YES;

Example App/Example App/ContentView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct ContentView: View {
125125
// using name as the unique identifier
126126
let lydia = Author.findOrCreate(column: "name", value: "Lydia Millet", using: .background)
127127

128-
var authors = [murakami, jk, lydia]
128+
let authors = [murakami, jk, lydia]
129129

130130
for _ in 0..<10 {
131131
let newItem = Book.findOrCreate(id: UUID().uuidString, using: .background)

Scripts/build-core-data-plus-docs.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ echo "<script>window.location.href += \"/documentation/coredataplus\"</script>"
1717

1818
#git add .;
1919
#git commit -m 'Documentation update';
20-
#git push origin docs;
20+
#git push origin docs;
File renamed without changes.
File renamed without changes.

Sources/CoreDataPlus/ManagedObjectCountable.swift renamed to Sources/CoreDataPlus/ManagedObject/ManagedObjectCountable.swift

File renamed without changes.

Sources/CoreDataPlus/ManagedObjectDeletable.swift renamed to Sources/CoreDataPlus/ManagedObject/ManagedObjectDeletable.swift

File renamed without changes.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import CoreData
2+
import Foundation
3+
4+
public protocol ManagedObjectFind where Self: NSFetchRequestResult {
5+
// Tip: You will probably want to define id, as part of the Identifiable protocol. If you add this as a column in your db, you get automatic conformance. If your NSManagedObject doesn't have an `id` property in the database, you'd implement this:
6+
// var id: String { get set }
7+
8+
init(context: NSManagedObjectContext)
9+
static func entity() -> NSEntityDescription
10+
static func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>
11+
}
12+
13+
public extension ManagedObjectFind {
14+
15+
/// Finds an instance of the NSManagedObject that has a column (property) matching the passed value. If it doesn't exist in the database, creates one, and returns it.
16+
/// - Parameters:
17+
/// - column: Name of column that uniquely identifies a row (primary key).
18+
/// - value: Value of the primary key.
19+
/// - context: NSManagedObjectContext to use
20+
/// - Returns: An instance of the object, or nil
21+
22+
/// Finds an instance of the NSManagedObject that has a column (property) matching the passed value. If it doesn't exist in the database, returns nil.
23+
/// - Parameters:
24+
/// - column: Name of column that uniquely identifies a row (primary key).
25+
/// - value: Value of the primary key.
26+
/// - using: Optional. Specify `.foreground` for the main view context (operates on the main thread). Use `.background` to use a shared background context that automatically merges into the view context. Use `.custom(nsManagedObjectContext:)` to choose your own NSManagedObjectContext.
27+
/// - Returns: An instance of the object, or nil.
28+
static func find(column: String, value: Any, using: ContextMode = .foreground) -> Self? {
29+
let context = contextModeToNSManagedObjectContext(using)
30+
31+
return find(column: column, value: value, context: context)
32+
}
33+
34+
/// Same as `find(column: String, value: Any, using: ContextMode = .foreground)`, but allows you to pass your own `NSManagedObjectContext`.
35+
static func find(column: String, value: Any, context: NSManagedObjectContext) -> Self? {
36+
37+
let request = NSFetchRequest<Self>()
38+
request.predicate = Predicate("\(column) = %@", value)
39+
request.fetchLimit = 1
40+
request.entity = entity()
41+
42+
do {
43+
let objects: [Self] = try context.fetch(request)
44+
45+
if let object = objects.first {
46+
return object
47+
}
48+
} catch {
49+
CoreDataPlusLogger.shared.log("FindButDoNotCreateById context fetch failure: \(error.localizedDescription)")
50+
}
51+
52+
return nil
53+
}
54+
55+
/// Same as `find(column: String, value: Any, ...`, but with the column name set to `id`.
56+
static func find(id: String, using: ContextMode = .foreground) -> Self? {
57+
return find(column: "id", value: id, using: using)
58+
}
59+
60+
/// Same as `find(column: String, value: Any, ...`, but with the column name set to `id`.
61+
static func find(id: String, context: NSManagedObjectContext) -> Self? {
62+
return find(column: "id", value: id, context: context)
63+
}
64+
65+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import CoreData
2+
import Foundation
3+
4+
public protocol ManagedObjectFindOrCreateBy where Self: NSFetchRequestResult {
5+
// Tip: You will probably want to define id, as part of the Identifiable protocol. If you add this as a column in your db, you get automatic conformance. If your NSManagedObject doesn't have an `id` property in the database, you'd implement this:
6+
// var id: String { get set }
7+
8+
init(context: NSManagedObjectContext)
9+
static func entity() -> NSEntityDescription
10+
static func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>
11+
}
12+
13+
public extension ManagedObjectFindOrCreateBy {
14+
/// Finds an instance of the NSManagedObject that has a column (property) matching the passed value. If it doesn't exist in the database, creates one, and returns it.
15+
/// - Parameters:
16+
/// - column: Name of column that uniquely identifies a row (primary key).
17+
/// - value: Value of the primary key.
18+
/// - using: Optional. Specify `.foreground` for the main view context (operates on the main thread). Use `.background` to use a shared background context that automatically merges into the view context. Use `.custom(nsManagedObjectContext:)` to choose your own NSManagedObjectContext.
19+
/// - Returns: An instance of the object
20+
static func findOrCreate(column: String, value: Any, using: ContextMode = .foreground) -> Self {
21+
let context = contextModeToNSManagedObjectContext(using)
22+
23+
return findOrCreate(column: column, value: value, context: context)
24+
}
25+
26+
/// Same as `findOrCreate(column: String, value: Any, using: ContextMode = .foreground)`, but allows you to pass your own `NSManagedObjectContext`.
27+
static func findOrCreate(column: String, value: Any, context: NSManagedObjectContext) -> Self {
28+
let request = NSFetchRequest<Self>()
29+
request.predicate = Predicate("\(column) = %@", value)
30+
request.entity = entity()
31+
32+
do {
33+
let objects: [Self] = try context.fetch(request)
34+
35+
if let object = objects.first {
36+
return object
37+
}
38+
} catch {
39+
CoreDataPlusLogger.shared.log("findOrCreate context fetch failure: \(error.localizedDescription)")
40+
}
41+
42+
let object = Self(context: context)
43+
44+
if let object = object as? NSManagedObject {
45+
object.setValue(value, forKey: column)
46+
}
47+
48+
return object
49+
}
50+
51+
/// Same as `findOrCreate(column: String, value: Any, ...`, but with the column name set to `id`.
52+
static func findOrCreate(id: String, using: ContextMode = .foreground) -> Self {
53+
let context = contextModeToNSManagedObjectContext(using)
54+
55+
return findOrCreate(column: "id", value: id, context: context)
56+
}
57+
58+
/// Same as `findOrCreate(column: String, value: Any, ...`, but with the column name set to `id`.
59+
static func findOrCreate(id: String, context: NSManagedObjectContext) -> Self {
60+
return findOrCreate(column: "id", value: id, context: context)
61+
}
62+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
/// Shortcut for adding all ManagedObject extensions
2-
public typealias ManagedObjectPlus = ManagedObjectCountable & ManagedObjectDeletable & ManagedObjectSearchable & ManagedObjectFindOrCreateBy
2+
public typealias ManagedObjectPlus = ManagedObjectCountable & ManagedObjectDeletable & ManagedObjectSearchable & ManagedObjectFindOrCreateBy & ManagedObjectFind

0 commit comments

Comments
 (0)