Page updated Nov 11, 2023

Integrate your app

Next you'll use the generated model to create, update, query, and delete data. In this section you'll initialize DataStore, and then manipulate Todo items.

Configure Amplify and DataStore

First, you'll add the DataStore plugin and configure Amplify.

  1. Open the main file of the application (TodoApp.swift) and add the following import statements at the top of the file:
import Amplify import AWSDataStorePlugin
1import Amplify
2import AWSDataStorePlugin
  1. In the same file, create a function to configure Amplify:
func configureAmplify() { let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels()) do { try Amplify.add(plugin: dataStorePlugin) try Amplify.configure() print("Initialized Amplify"); } catch { // simplified error handling for the tutorial print("Could not initialize Amplify: \(error)") } }
1func configureAmplify() {
2 let dataStorePlugin = AWSDataStorePlugin(modelRegistration: AmplifyModels())
3 do {
4 try Amplify.add(plugin: dataStorePlugin)
5 try Amplify.configure()
6 print("Initialized Amplify");
7 } catch {
8 // simplified error handling for the tutorial
9 print("Could not initialize Amplify: \(error)")
10 }
11}
  1. Now call the configureAmplify() function in your App's initializer.
@main struct TodoApp: App { // Add a default initializer and configure Amplify init() { configureAmplify() } // Additional functions... }
1@main
2struct TodoApp: App {
3 // Add a default initializer and configure Amplify
4 init() {
5 configureAmplify()
6 }
7
8 // Additional functions...
9}
  1. Build and run the application. In the Xcode console window, you'll see a log line indicating success:

    Initialized Amplify
    1Initialized Amplify

    Optionally, if you'd like to adjust the log level, you can do this by updating the Amplify.Logging.logLevel variable.

    For example, you can add the following line of code to the configureAmplify() function before calling Amplify.configure():

    Amplify.Logging.logLevel = .info
    1Amplify.Logging.logLevel = .info

    Setting the log level to .info, re-building and re-running the application should render additional log statements:

    [Amplify] Configuring Initialized Amplify
    1[Amplify] Configuring
    2Initialized Amplify

Manipulating data

Create a Todo

Next, you'll create a Todo and save it to DataStore.

  1. Open ContentView.swift and add the following import statements at the top of the file:
import Amplify
1import Amplify
  1. In the same file (ContentView.swift), update the body view to call a function called performOnAppear() using the .task() modifier:
var body: some View { Text("Hello, World!") .task { await performOnAppear() } }
1var body: some View {
2 Text("Hello, World!")
3 .task {
4 await performOnAppear()
5 }
6}
  1. In the same file, add an async function called performOnAppear():
func performOnAppear() async { do { let item = Todo(name: "Build iOS Application", description: "Build an iOS application using Amplify") let savedItem = try await Amplify.DataStore.save(item) print("Saved item: \(savedItem.name)") } catch { print("Could not save item to DataStore: \(error)") } }
1func performOnAppear() async {
2 do {
3 let item = Todo(name: "Build iOS Application",
4 description: "Build an iOS application using Amplify")
5 let savedItem = try await Amplify.DataStore.save(item)
6 print("Saved item: \(savedItem.name)")
7 } catch {
8 print("Could not save item to DataStore: \(error)")
9 }
10}

This code creates a Todo item with two properties: a name and a description, and then calls Amplify.DataStore.save(:) in order to store it on DataStore.

  1. After making the preceding updates to the ContentView.swift file, your code should look like the following:
import SwiftUI import Amplify struct ContentView: View { var body: some View { Text("Hello, World!") .task { await performOnAppear() } } func performOnAppear() async { do { let item = Todo(name: "Build iOS Application", description: "Build an iOS application using Amplify") let savedItem = try await Amplify.DataStore.save(item) print("Saved item: \(savedItem.name)") } catch { print("Could not save item to DataStore: \(error)") } } }
1import SwiftUI
2import Amplify
3
4struct ContentView: View {
5
6 var body: some View {
7 Text("Hello, World!")
8 .task {
9 await performOnAppear()
10 }
11 }
12
13 func performOnAppear() async {
14 do {
15 let item = Todo(name: "Build iOS Application",
16 description: "Build an iOS application using Amplify")
17 let savedItem = try await Amplify.DataStore.save(item)
18 print("Saved item: \(savedItem.name)")
19 } catch {
20 print("Could not save item to DataStore: \(error)")
21 }
22 }
23}
  1. Build and run the application. In the console output, you'll see an indication that the item was saved successfully:
Initialized Amplify Saved item: Build iOS Application
1Initialized Amplify
2Saved item: Build iOS Application
  1. Replace the item with a new Todo to save an additional item. Let's change the name and description, and add a priority:
let item = Todo(name: "Finish quarterly taxes", priority: .high, description: "Taxes are due for the quarter next week")
1let item = Todo(name: "Finish quarterly taxes",
2 priority: .high,
3 description: "Taxes are due for the quarter next week")
  1. Build and run the application. In the console output, you'll see an indication that the item was saved successfully:
Initialized Amplify Saved item: Finish quarterly taxes
1Initialized Amplify
2Saved item: Finish quarterly taxes

Query Todos

Now that you have some data in DataStore, you can run queries to retrieve those records.

  1. Edit your performOnAppear() method to remove the item creation and save operations, and replace it with the following code:
do { let todos = try await Amplify.DataStore.query(Todo.self) for todo in todos { print("==== Todo ====") print("Name: \(todo.name)") if let description = todo.description { print("Description: \(description)") } if let priority = todo.priority { print("Priority: \(priority)") } } } catch { print("Could not query DataStore: \(error)") }
1do {
2 let todos = try await Amplify.DataStore.query(Todo.self)
3 for todo in todos {
4 print("==== Todo ====")
5 print("Name: \(todo.name)")
6 if let description = todo.description {
7 print("Description: \(description)")
8 }
9 if let priority = todo.priority {
10 print("Priority: \(priority)")
11 }
12 }
13} catch {
14 print("Could not query DataStore: \(error)")
15}
  1. Build and run the application. In the console output, you'll see both items returned:
Initialized Amplify ==== Todo ==== Name: Build an iOS application using Amplify Description: Build an iOS application using Amplify ==== Todo ==== Name: Finish quarterly taxes Description: Taxes are due for the quarter next week Priority: high
1Initialized Amplify
2==== Todo ====
3Name: Build an iOS application using Amplify
4Description: Build an iOS application using Amplify
5==== Todo ====
6Name: Finish quarterly taxes
7Description: Taxes are due for the quarter next week
8Priority: high
  1. Queries can also contain predicate filters. These will query for specific objects matching a certain condition.

The following predicates are supported:

Strings

eq ne le lt ge gt contains notContains beginsWith between

Numbers

eq ne le lt ge gt between

Lists

contains notContains

To use a predicate, pass an additional argument into your query. For example, you can use the following code to see all high priority items:

let todos = try await Amplify.DataStore.query(Todo.self, where: Todo.keys.priority.eq(Priority.high))
1let todos = try await Amplify.DataStore.query(Todo.self,
2 where: Todo.keys.priority.eq(Priority.high))

In the above code, notice the addition of the predicate parameter as the second argument.

  1. Run the application. In the console output, you'll see only the high priority item returned:
Initialized Amplify ==== Todo ==== Name: Finish quarterly taxes Description: Taxes are due for the quarter next week Priority: high
1Initialized Amplify
2==== Todo ====
3Name: Finish quarterly taxes
4Description: Taxes are due for the quarter next week
5Priority: high

Update a Todo

You may want to change the contents of a record. Below, you'll query for a record, create a copy of it, modify it, and save it back to DataStore.

  1. Edit your performOnAppear() method to remove anything related to DataStore and replace it with the following code:
do { let todos = try await Amplify.DataStore.query(Todo.self, where: Todo.keys.name.eq("Finish quarterly taxes")) guard todos.count == 1, var updatedTodo = todos.first else { print("Did not find exactly one todo, bailing") return } updatedTodo.name = "File quarterly taxes" let savedTodo = try await Amplify.DataStore.save(updatedTodo) print("Updated item: \(savedTodo.name)") } catch { print("Unable to perform operation: \(error)") }
1do {
2 let todos = try await Amplify.DataStore.query(Todo.self,
3 where: Todo.keys.name.eq("Finish quarterly taxes"))
4 guard todos.count == 1, var updatedTodo = todos.first else {
5 print("Did not find exactly one todo, bailing")
6 return
7 }
8 updatedTodo.name = "File quarterly taxes"
9 let savedTodo = try await Amplify.DataStore.save(updatedTodo)
10 print("Updated item: \(savedTodo.name)")
11} catch {
12 print("Unable to perform operation: \(error)")
13}
  1. Build and run the application. In your console output, you'll see an indication that the item was updated successfully:

    Initialized Amplify Updated item: File quarterly taxes
    1Initialized Amplify
    2Updated item: File quarterly taxes

Delete a Todo

To round out CRUD operations, you'll query for a record and then delete it from DataStore.

  1. Edit your performOnAppear() method to remove anything related to DataStore and replace it with the following code:
do { let todos = try await Amplify.DataStore.query(Todo.self, where: Todo.keys.name.eq("File quarterly taxes")) guard todos.count == 1, let toDeleteTodo = todos.first else { print("Did not find exactly one todo, bailing") return } try await Amplify.DataStore.delete(toDeleteTodo) print("Deleted item: \(toDeleteTodo.name)") } catch { print("Unable to perform operation: \(error)") }
1do {
2 let todos = try await Amplify.DataStore.query(Todo.self,
3 where: Todo.keys.name.eq("File quarterly taxes"))
4 guard todos.count == 1, let toDeleteTodo = todos.first else {
5 print("Did not find exactly one todo, bailing")
6 return
7 }
8 try await Amplify.DataStore.delete(toDeleteTodo)
9 print("Deleted item: \(toDeleteTodo.name)")
10} catch {
11 print("Unable to perform operation: \(error)")
12}
  1. Build and run the application. In the console output, you'll see an indication that the item was deleted successfully:
Initialized Amplify Deleted item: File quarterly taxes
1Initialized Amplify
2Deleted item: File quarterly taxes

Almost done

You just reached a very cool checkpoint. You have a fully featured CRUD application that saves and retrieves data in the local device, which means the app works without an AWS account and even without internet connection.

Next, let's connect it to AWS and make sure the data available in the cloud.