A preface.

This article is probably the first Swift UI-related note I’ve written.

This is really tough. It’s new. Domestic documents are really few and far between, and foreign documents are really few. Basically, the ones searched out are UIKit. Official documents, is also a long story, basically in, I want to achieve a function, and then to search a variety of posts, filter out useless posts, find useful points, of course, is often simply can not find useful posts, and then go to YouTube to see a variety of tutorials, and then found: Oh! There is this method! Then go to the official document search, look at the attributes, their call……

Just this core data I toss about for nearly a week, finally found that the original is still the official good…..

Having a little fun learning swift UI by yourself, now we’re getting down to business.

Core Data is apple’s official local database, but the files it stores are actually SQLite files. It can be backed up and synchronized via icloud, which I’ll cover in an extra icloud document. .

2. Environmental

Here is my current environment:

  • System: macOS Big Sur 11.4
  • Xcode: Version 12.5 (12E262)
  • Swift: 5.4

3. Operation procedure

1. Create projects

When creating a project, you can directly select the Use Core Data option and Xcode will generate a demo directly in contentView.swift.

2. View related files

If you do not select Use Core Data, you will see the following files:

  • .xcdatamodeId
  • Persistence.swift

3. Create a core data table

Click on the < your-project-name >.xcDatamodeid file to take you to the page.

CONFIGURATIONS you can see that the Default CONFIGURATIONS are Default and the Default ENITITIES are Item, which correspond to the library and table in the SQL respectively.

Then click on Item and you can see its field, which has a default TIMESTAMP field.

To Add ENTITIES, click the Add Entity button at the bottom.

To add Attributes, click the + in Attributes on the right, noting that the field is of a type.

For example, add username and age to the default Item.

4. Operate Core Data at the code level

1) check

@Environment(\.managedObjectContext) private var viewContext

@FetchRequest(
  sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
  animation: .default)
private var items: FetchedResults<Item>

// The convenience items in the body can be used
Copy the code

2) new

private func addItem(a) {
  withAnimation {
    let newItem = Item(context: viewContext)
    newItem.timestamp = Date(a)do {
      try viewContext.save()
    } catch {
      // 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.
      let nsError = error as NSError
      fatalError("Unresolved error \(nsError).\(nsError.userInfo)")}}}Copy the code

Xcode automatically generates the new function above. If you want to customize the new function, you can change it like this:

// Add Attributes to modify the project as described above
private func addItem(username: String.age: Int16) {
  withAnimation {
    let newItem = Item(context: viewContext)
    newItem.username = username
    newItem.age = age
    newItem.timestamp = Date(a)do {
      try viewContext.save()
    } catch {
      // 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.
      let nsError = error as NSError
      fatalError("Unresolved error \(nsError).\(nsError.userInfo)")}}}Copy the code

3) delete

private func deleteItems(offsets: IndexSet) {
  withAnimation {
    offsets.map { items[$0] }.forEach(viewContext.delete)

    do {
      try viewContext.save()
    } catch {
      // 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.
      let nsError = error as NSError
      fatalError("Unresolved error \(nsError).\(nsError.userInfo)")}}}Copy the code

4) summary

In the default generated code, there is a toolbar that works on MacOS, but only EditionButton() works on ios. For demonstration purposes, add a Button to add data.

Secondly, it should be noted that when writing code in Xcode, the canvas on the right side will render in real time, and the data in the list is not the data in Core Data, but the default generated Persistence. The demo data generated in Swift can only be viewed, not taken seriously. You can only manipulate Core Data while the emulator/entity is compiling.

The following is the modified contentView.swift file:

//
// ContentView.swift
// HelloKuari
//
// Created by Kuari on 2021/6/5.
//

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>

    var body: some View {
        
        VStack {
            List {
                ForEach(items) { item in
                    Text("Tom: \(item.username!) age: \(item.age) time :  \(item.timestamp!, formatter: itemFormatter)")
                }
                .onDelete(perform: deleteItems)
            }
            
            // Add a button to add data
            Button(action: {
                addItem(username: "tom", age: 12)
            }, label: {
                Text("Add Item")}}}private func addItem(username: String.age: Int16) {
        withAnimation {
            let newItem = Item(context: viewContext)
            newItem.username = username
            newItem.age = age
            newItem.timestamp = Date(a)do {
                try viewContext.save()
            } catch {
                // 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.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError).\(nsError.userInfo)")}}}private func deleteItems(offsets: IndexSet) {
        withAnimation {
            offsets.map { items[$0] }.forEach(viewContext.delete)

            do {
                try viewContext.save()
            } catch {
                // 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.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError).\(nsError.userInfo)")}}}}private let itemFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .medium
    return formatter
}()

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}
Copy the code

Then click the Run button at the top left to compile and run.

It starts out as a blank, and when you click the Add Item button, you start adding data.

For records that can be deleted by right – swipe, it is the onDelete method of List.

4. Original link

Github.com/Kuari/Blog/…

Five epilogue.

This article is for novices and also records the pits I have stepped on. Because of the lack of documents at present and the lack of swift development partners around me, I can only rely on my own exploration. If there is a better way, please kindly advise.

Continue to record behind the pit……