https://github.com/jonathanp-code/simple-todo-app
ToDo is a lightweight and intuitive to-do app built with SwiftUI. It allows users to quickly add, manage, and complete tasks with a clean and minimal design. Perfect for staying organized without distractions.
https://github.com/jonathanp-code/simple-todo-app
app easy mit-license simple swift swiftui todo todoapp todolist xcode
Last synced: 6 months ago
JSON representation
ToDo is a lightweight and intuitive to-do app built with SwiftUI. It allows users to quickly add, manage, and complete tasks with a clean and minimal design. Perfect for staying organized without distractions.
- Host: GitHub
- URL: https://github.com/jonathanp-code/simple-todo-app
- Owner: JonathanP-code
- License: mit
- Created: 2025-03-22T08:38:36.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-03-26T15:54:04.000Z (11 months ago)
- Last Synced: 2025-04-06T22:39:16.232Z (10 months ago)
- Topics: app, easy, mit-license, simple, swift, swiftui, todo, todoapp, todolist, xcode
- Language: Swift
- Homepage:
- Size: 21.5 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ToDo App
A simple and elegant To-Do app built with **SwiftUI**, designed to help users efficiently manage their tasks. The app allows users to add, mark as complete, and delete tasks, with data persistence using **UserDefaults**.
The ToDo app is still only very simple but please feel free to implement your own ideas!
---
## 📂 Project Overview
- **Platform:** iOS (SwiftUI)
- **Language:** Swift
- **Storage:** UserDefaults
- **Features:** Task creation, completion toggle, deletion, and data persistence.
---

---
## ✨ Features
✅ **Add New Tasks** – Easily add new tasks using the input field.
✅ **Mark Tasks as Completed** – Tap the task icon to toggle completion.
✅ **Delete Tasks** – Remove unwanted tasks with a trash button.
✅ **Data Persistence** – Stores tasks locally using `UserDefaults`.
---
## 📥 Installation
To set up the project locally, follow these steps:
### **1️⃣ Clone the Repository**
```sh
git clone https://github.com/your-username/todo-app.git
cd todo-app
```
### **2️⃣ Open in Xcode**
- Open `ToDoApp.xcodeproj` in **Xcode**.
- Select a target device (iPhone simulator or real device).
### **3️⃣ Run the App**
Click ▶️ **Run** in Xcode to launch the app.
---
## 🛠 Usage Guide
### **Adding a Task**
1. Enter a task title in the **text field**.
2. Press the ➕ **plus button** to add the task.
### **Marking a Task as Completed**
- Tap the **circle icon** to toggle completion status.
- Completed tasks will appear with a **checkmark**.
### **Deleting a Task**
- Tap the **trash icon** next to a task to remove it.
---
## Code Structure
### **Task Model** (`Task.swift`)
```swift
struct Task: Identifiable, Codable {
var id = UUID()
var title: String
var isCompleted: Bool = false
}
```
### **ViewModel for Task Management** (`TaskViewModel.swift`)
```swift
class TaskViewModel: ObservableObject {
@Published var tasks: [Task] {
didSet {
saveTasks()
}
}
let tasksKey = "tasksKey"
init() {
if let data = UserDefaults.standard.data(forKey: tasksKey),
let decoded = try? JSONDecoder().decode([Task].self, from: data) {
tasks = decoded
} else {
tasks = []
}
}
func addTask(title: String) {
let newTask = Task(title: title)
tasks.append(newTask)
}
func removeTask(at offsets: IndexSet) {
tasks.remove(atOffsets: offsets)
}
func toggleTaskCompletion(_ task: Task) {
if let index = tasks.firstIndex(where: { $0.id == task.id }) {
tasks[index].isCompleted.toggle()
}
}
private func saveTasks() {
if let encoded = try? JSONEncoder().encode(tasks) {
UserDefaults.standard.set(encoded, forKey: tasksKey)
}
}
}
```
### **Main View** (`ContentView.swift`)
```swift
struct ContentView: View {
@StateObject private var viewModel = TaskViewModel()
@State private var newTaskTitle = ""
var body: some View {
ZStack {
LinearGradient(gradient: Gradient(colors: [Color.black, Color.gray]), startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
VStack(spacing: 50) {
Text("")
.italic()
.bold()
.font(.system(size: 50, weight: .medium))
.padding(CGFloat.zero)
.fontWeight(.bold)
.foregroundColor(.white)
HStack {
TextField("", text: $newTaskTitle)
.hoverEffect(.highlight)
.padding()
.background(Color.black.opacity(1))
.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(Color.yellow, lineWidth: 3)
)
.foregroundColor(.white)
Button(action: addTask) {
Image(systemName: "plus.app.fill")
.font(.system(size: 60))
.foregroundColor(.yellow)
}
}
.padding(.horizontal)
ScrollView {
VStack(spacing: 10) {
ForEach(viewModel.tasks) { task in
HStack {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
.foregroundColor(task.isCompleted ? .green : .black)
.onTapGesture {
viewModel.toggleTaskCompletion(task)
}
Text(task.title)
.foregroundColor(.black)
.font(.system(size: 18, weight: .medium))
.strikethrough(task.isCompleted, color: .white)
Spacer()
Button(action: {
if let index = viewModel.tasks.firstIndex(where: { $0.id == task.id }) {
viewModel.removeTask(at: IndexSet(integer: index))
}
}) {
Image(systemName: "trash")
.foregroundColor(.red)
}
}
.padding()
.background(Color.gray.opacity(0.3))
.cornerRadius(12)
}
}
.padding(.horizontal)
}
.frame(maxHeight: .infinity)
}
.padding(.top, 20)
}
.tabItem {
Image(systemName: "list.bullet")
Text("Tasks")
}
}
private func addTask() {
guard !newTaskTitle.isEmpty else { return }
viewModel.addTask(title: newTaskTitle)
newTaskTitle = ""
}
}
```
---
## 🚀 Future Improvements
- ❌ **Cloud Syncing** (iCloud or Firebase for multi-device support)
- ✅ **Custom Themes** (Light & Dark Mode)
- ✅ **Deadline & Notifications** (Reminders for tasks)
- ✅ **Drag & Drop Sorting** (Rearrange tasks dynamically)
---
## License
This project is open-source under the **MIT License**.
---
## Contributing
Contributions are welcome! If you find a bug or have suggestions, feel free to open an **issue** or submit a **pull request**.
---
## 🌟 Show Your Support
If you like this project, please ⭐ star the repository on GitHub!