-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
796 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
Example App/Example App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
Example App/Example App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
11 changes: 11 additions & 0 deletions
11
Example App/Example App/Assets.xcassets/AccentColor.colorset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
Example App/Example App/Assets.xcassets/AppIcon.appiconset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "universal", | ||
"platform" : "ios", | ||
"size" : "1024x1024" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Foundation | ||
import CoreData | ||
import CoreDataPlus | ||
|
||
extension Author: ManagedObjectCountable, | ||
ManagedObjectSearchable, | ||
ManagedObjectDeletable, | ||
ManagedObjectFindOrCreateBy { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Foundation | ||
import CoreData | ||
import CoreDataPlus | ||
|
||
extension Book: ManagedObjectCountable, | ||
ManagedObjectSearchable, | ||
ManagedObjectDeletable, | ||
ManagedObjectFindOrCreateBy { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// | ||
|
||
import Foundation | ||
import SwiftUI | ||
import CoreData | ||
import CoreDataPlus | ||
|
||
struct BookDetailView: View { | ||
@Environment(\.managedObjectContext) private var viewContext | ||
@ObservedObject var book: Book | ||
|
||
public var body: some View { | ||
ScrollView { | ||
VStack { | ||
Text(book.title ?? "No title") | ||
.font(.title) | ||
|
||
ForEach((book.authors?.allObjects as? [Author] ?? []), id: \.self) { author in | ||
HStack(spacing: 5) { | ||
Text(author.name ?? "No name") | ||
Button("❌", action: { | ||
book.removeFromAuthors(author) | ||
}) | ||
} | ||
} | ||
|
||
|
||
VStack(spacing: 100) { | ||
Button("Add author\nHaruki Murakami", action: { | ||
let murakami = Author.findOrCreate(column: "name", value: "Haruki Murakami", context: viewContext) | ||
book.addToAuthors(murakami) | ||
}) | ||
.buttonStyle(.bordered) | ||
|
||
Button("Add author\nMurakami, J.K., or Millet", action: { | ||
let names = [ | ||
"Haruki Murakami", | ||
"J. K. Rowling", | ||
"Lydia Millet" | ||
] | ||
|
||
book.addToAuthors(Author.findOrCreate(column: "name", value: names.randomElement()!, context: viewContext)) | ||
}) | ||
.buttonStyle(.bordered) | ||
|
||
Button("Add new fictional author", action: { | ||
book.addToAuthors(Author.findOrCreate(column: "name", value: "Author \(Int.random(in: 1...1000))", context: viewContext)) | ||
}) | ||
.buttonStyle(.bordered) | ||
|
||
Button("Add new fictional author", action: { | ||
book.addToAuthors(Author.findOrCreate(column: "name", value: "Author \(Int.random(in: 1...1000))", context: viewContext)) | ||
}) | ||
.buttonStyle(.bordered) | ||
} | ||
|
||
|
||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// | ||
// ContentView.swift | ||
// Example App | ||
// | ||
// Created by Will Jessop on 10/26/22. | ||
// | ||
|
||
import SwiftUI | ||
import CoreData | ||
import CoreDataPlus | ||
|
||
struct ContentView: View { | ||
@Environment(\.managedObjectContext) private var viewContext | ||
|
||
@FetchRequest( | ||
sortDescriptors: [NSSortDescriptor(keyPath: \Book.title, ascending: true)], | ||
animation: .default) | ||
private var books: FetchedResults<Book> | ||
|
||
var body: some View { | ||
NavigationView { | ||
List { | ||
Section(footer: VStack(alignment: .leading) { | ||
Spacer() | ||
HStack { | ||
Image(systemName: "plus") | ||
Text("Add test data").fontWeight(.bold) | ||
} | ||
.foregroundColor(.blue) | ||
.onTapGesture { | ||
self.addTestData() | ||
} | ||
Spacer(minLength: 20) | ||
|
||
Text("Saving").underline() | ||
Text("Core Data is saved to disk when the app goes into the background.\n\nOr you can click the \"Save all\" button.") | ||
Spacer(minLength: 20) | ||
|
||
Text("New Book object with id = 100").underline() | ||
Text("Demonstrates what happens when you create a variable using findOrCreate(id:)") | ||
Spacer(minLength: 20) | ||
|
||
}) { | ||
ForEach(books) { book in | ||
NavigationLink { | ||
BookDetailView(book: book) | ||
} label: { | ||
Text(book.title!) | ||
Text("\((book.authors?.allObjects as! [Author]).map { author in author.name! }.joined())") | ||
.font(.caption) | ||
} | ||
} | ||
.onDelete(perform: deleteItems) | ||
} | ||
|
||
|
||
|
||
} | ||
.toolbar { | ||
ToolbarItemGroup(placement: .navigationBarTrailing) { | ||
|
||
|
||
Button(action: addBook) { | ||
Label("Add Book", systemImage: "plus") | ||
} | ||
|
||
Button(action: deleteAllBooksAndAuthors) { | ||
Label("Delete all books and authors", systemImage: "trash") | ||
} | ||
|
||
} | ||
|
||
ToolbarItemGroup(placement: .navigationBarLeading) { | ||
Button("New Book object with id = 100", action: { | ||
let book = Book.findOrCreate(id: "100", context: viewContext) | ||
book.title = "Book(id=100) last touched \(Date().formatted(date: .abbreviated, time: .complete))" | ||
}) | ||
} | ||
|
||
ToolbarItemGroup(placement: .bottomBar) { | ||
|
||
Button("Save all", action: { | ||
try! viewContext.save() | ||
}) | ||
.buttonStyle(.borderedProminent) | ||
|
||
Spacer() | ||
Button("Delete authors", action: { | ||
Author.destroyAll(context: viewContext) | ||
}) | ||
.foregroundColor(.red) | ||
|
||
Button("Delete books", action: { | ||
Book.destroyAll(context: viewContext) | ||
}) | ||
.foregroundColor(.red) | ||
|
||
|
||
|
||
|
||
} | ||
|
||
} | ||
Text("Select an item") | ||
} | ||
.navigationViewStyle(.stack) | ||
} | ||
|
||
private func addTestData() { | ||
// create some authors | ||
// using the name field as the unique identifier | ||
// TODO: add better docs on how to handle id/identifiable with core data (not library-specific) | ||
let murakami = Author.findOrCreate(column: "name", value: "Haruki Murakami", context: viewContext) | ||
let jk = Author.findOrCreate(column: "name", value: "J. K. Rowling", context: viewContext) | ||
|
||
// using id as the unique identifier | ||
let lydia = Author.findOrCreate(id: "1234", context: viewContext) | ||
lydia.name = "Lydia Millet" | ||
|
||
var authors = [murakami, jk, lydia] | ||
|
||
for _ in 0..<10 { | ||
let newItem = Book.findOrCreate(id: UUID().uuidString, context: viewContext) | ||
newItem.title = "Harry Potter Vol. \(Int.random(in: 1...1000))" | ||
|
||
newItem.addToAuthors(authors.randomElement()!) | ||
|
||
// add a 2nd author to some books | ||
if Int.random(in: 1...100) > 50 { | ||
newItem.addToAuthors(authors.randomElement()!) | ||
} | ||
} | ||
} | ||
private func deleteAllBooks() { | ||
Book.destroyAll(context: viewContext) | ||
} | ||
private func deleteAllAuthors() { | ||
Author.destroyAll(context: viewContext) | ||
} | ||
private func deleteAllBooksAndAuthors() { | ||
Author.destroyAll(context: viewContext) | ||
Book.destroyAll(context: viewContext) | ||
} | ||
|
||
private func addBook() { | ||
let newBook = Book.findOrCreate(id: UUID().uuidString, context: viewContext) | ||
newBook.title = "Book \(Int.random(in: 1...1000))" | ||
} | ||
|
||
private func deleteItems(offsets: IndexSet) { | ||
withAnimation { | ||
offsets.map { books[$0] }.forEach(viewContext.delete) | ||
} | ||
} | ||
} | ||
|
8 changes: 8 additions & 0 deletions
8
Example App/Example App/Example_App.xcdatamodeld/.xccurrentversion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>_XCCurrentVersionName</key> | ||
<string>Example_App.xcdatamodel</string> | ||
</dict> | ||
</plist> |
13 changes: 13 additions & 0 deletions
13
Example App/Example App/Example_App.xcdatamodeld/Example_App.xcdatamodel/contents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21279" systemVersion="21G72" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> | ||
<entity name="Author" representedClassName="Author" syncable="YES" codeGenerationType="class"> | ||
<attribute name="id" optional="YES" attributeType="String"/> | ||
<attribute name="name" attributeType="String" defaultValueString=""/> | ||
<relationship name="books" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Book" inverseName="authors" inverseEntity="Book"/> | ||
</entity> | ||
<entity name="Book" representedClassName="Book" syncable="YES" codeGenerationType="class"> | ||
<attribute name="id" attributeType="String"/> | ||
<attribute name="title" attributeType="String" defaultValueString=""/> | ||
<relationship name="authors" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Author" inverseName="books" inverseEntity="Author"/> | ||
</entity> | ||
</model> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// Example_AppApp.swift | ||
// Example App | ||
// | ||
// Created by Will Jessop on 10/26/22. | ||
// | ||
|
||
import SwiftUI | ||
|
||
@main | ||
struct Example_AppApp: App { | ||
let persistenceController = PersistenceController.shared | ||
@Environment(\.scenePhase) private var phase | ||
|
||
var body: some Scene { | ||
WindowGroup { | ||
ContentView() | ||
.environment(\.managedObjectContext, persistenceController.container.viewContext) | ||
} | ||
.onChange(of: phase) { newPhase in | ||
switch newPhase { | ||
case .background: | ||
try! persistenceController.container.viewContext.save() | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// | ||
// Persistence.swift | ||
// Example App | ||
// | ||
// Created by Will Jessop on 10/26/22. | ||
// | ||
|
||
import CoreData | ||
import CoreDataPlus | ||
|
||
struct PersistenceController { | ||
static let shared = PersistenceController() | ||
|
||
static var preview: PersistenceController = { | ||
let result = PersistenceController(inMemory: true) | ||
let viewContext = result.container.viewContext | ||
|
||
|
||
|
||
try! viewContext.save() | ||
|
||
return result | ||
}() | ||
|
||
let container: NSPersistentContainer | ||
|
||
init(inMemory: Bool = false) { | ||
container = NSPersistentContainer(name: "Example_App") | ||
if inMemory { | ||
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") | ||
} | ||
container.loadPersistentStores(completionHandler: { (storeDescription, error) in | ||
if let error = error as NSError? { | ||
// Replace this implementation with code to handle the error appropriately. | ||
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. | ||
|
||
/* | ||
Typical reasons for an error here include: | ||
* The parent directory does not exist, cannot be created, or disallows writing. | ||
* The persistent store is not accessible, due to permissions or data protection when the device is locked. | ||
* The device is out of space. | ||
* The store could not be migrated to the current model version. | ||
Check the error message to determine what the actual problem was. | ||
*/ | ||
fatalError("Unresolved error \(error), \(error.userInfo)") | ||
} | ||
}) | ||
container.viewContext.automaticallyMergesChangesFromParent = true | ||
} | ||
} |
Oops, something went wrong.
9c40a0e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.