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:

  ```swift
  import Amplify
  import AWSDataStorePlugin
  ```

1. In the same file, **create a function** to configure Amplify:
  ```swift
  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)")
      }
  }
  ```

1. Now **call the `configureAmplify()` function** in your App's initializer.
  
  ```swift
  @main
  struct TodoApp: App {
      // Add a default initializer and configure Amplify
      init() {
          configureAmplify()
      }

      // Additional functions...
  }
  ```

1. **Build and run** the application. In the Xcode console window, you'll see a log line indicating success:

    ```console
    Initialized 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()`:
    ```swift
    Amplify.Logging.logLevel = .info
    ```

    Setting the log level to `.info`, re-building and re-running the application should render additional log statements:
    ```console
    [Amplify] Configuring
    Initialized 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:
  ```swift
  import Amplify
  ```

1. In the same file (`ContentView.swift`), **update the body view**  to call a function called `performOnAppear()` using the `.task()` modifier:

  ```swift
  var body: some View {
      Text("Hello, World!")
          .task {
              await performOnAppear()
          }
  }
  ```

1. In the same file, **add an `async` function** called `performOnAppear()`:

  ```swift
  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)")
      }
  }
  ```
  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:

  ```swift
  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)")
          }
      }
  }
  ```

1. **Build and run** the application. In the console output, you'll see an indication that the item was saved successfully:

  ```console
  Initialized Amplify
  Saved 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:

  ```swift
  let item = Todo(name: "Finish quarterly taxes",
                  priority: .high,
                  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:

  ```console
  Initialized Amplify
  Saved 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:

  ```swift
  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)")
  }
  ```

1. **Build and run** the application. In the console output, you'll see both items returned:

  ```console
  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
  ```

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:

  ```swift
  let todos = try await Amplify.DataStore.query(Todo.self,
                                                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:

  ```console
  Initialized Amplify
  ==== Todo ====
  Name: Finish quarterly taxes
  Description: Taxes are due for the quarter next week
  Priority: 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:

  ```swift
  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)")
  }
  ```

1. **Build and run** the application. In your console output, you'll see an indication that the item was updated successfully:

    ```console
    Initialized Amplify
    Updated 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:

  ```swift
  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)")
  }
  ```

1. **Build and run** the application. In the console output, you'll see an indication that the item was deleted successfully:
  ```console
  Initialized Amplify
  Deleted 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.
