76 lines
3.9 KiB
Plaintext
76 lines
3.9 KiB
Plaintext
@Tutorial {
|
|
|
|
@Intro(title: "Model the task data") {
|
|
Data modelling is the art of creating a data model for representing real-world concepts in your code.
|
|
Create a model to represent the tasks.
|
|
}
|
|
|
|
@Section(title: "Create a new type to represent a task") {
|
|
@ContentAndMedia {
|
|
Create a `Task` type that holds a task's label, completion, and subtasks.
|
|
}
|
|
@Steps {
|
|
@Step {
|
|
Create a new file `Task.swift` by right-clicking on the `Sources` folder in the sidebar of GNOME Builder.
|
|
@Image(source: "NewFile.png", alt: "GNOME Builder's file context menu in the sidebar.")
|
|
}
|
|
@Step {
|
|
Declare a new structure called `Task`.
|
|
@Code(name: "Task.swift", file: "Task2.swift", previousFile: "Task1.swift")
|
|
}
|
|
@Step {
|
|
Create the three stored properties for a task's label, completion, and subtasks.
|
|
@Code(name: "Task.swift", file: "Task3.swift")
|
|
}
|
|
@Step {
|
|
In the user interface, there will be a text field for entering the label of a new task.
|
|
This means that a label is available before the instance of the type `Task` is created.
|
|
The other two properties have a default value at the beginning and can be modified after the task's creation.
|
|
Therefore, it makes sense to initialize these properties with default values.
|
|
|
|
Let `done` be `false` and `subtasks` be an empty array when adding a task.
|
|
@Code(name: "Task.swift", file: "Task4.swift")
|
|
}
|
|
@Step {
|
|
The check box for toggling the task's completion should not only indicate whether a task is done or not,
|
|
but also indicate the state of their subtasks. If the task is not completed, but some of their subtasks are, a mixed state design is visible.
|
|
|
|
It is a good practice to add computed properties to type definitions in order to be able to focus on the UI when creating views.
|
|
@Code(name: "Task.swift", file: "Task5.swift")
|
|
}
|
|
}
|
|
}
|
|
|
|
@Section(title: "Add protocol conformances") {
|
|
@ContentAndMedia {
|
|
As you've already seen in the Foundation section, a common way to make functions and types more flexible is by using protocols instead of concrete types.
|
|
Every type conforming to a certain protocol can then be used as a parameter.
|
|
In this section, you'll make the task type to protocols enabling tasks to be easily saved to the disk, listed in a view, or used for the window's title.
|
|
}
|
|
|
|
@Steps {
|
|
@Step {
|
|
Add `Codable` conformance.
|
|
|
|
`Codable` enables a Swift type to be easily converted into and out of JSON representation that can be saved on the disk.
|
|
@Code(name: "Task.swift", file: "Task6.swift", previousFile: "Task5.swift")
|
|
}
|
|
@Step {
|
|
Add `Identifiable` conformance.
|
|
|
|
`Identifiable` is a protocol that requires a type to have a property `id` that is unique across the app.
|
|
`UUID` is a type often used for IDs that stores a random value after its initialization and is defined on Swift's [Foundation library](https://developer.apple.com/documentation/foundation).
|
|
It is used by the ``List`` view that you'll later use to track how elements change.
|
|
@Code(name: "Task.swift", file: "Task7.swift")
|
|
}
|
|
@Step {
|
|
Add `CustomStringConvertible` conformance.
|
|
|
|
This will allow the `Task` type to be used as a destination in the ``NavigationView`` that will be used for navigating subtasks, making the parent task the window's title.
|
|
@Code(name: "Task.swift", file: "Task8.swift")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|