Skip to content

Instantly share code, notes, and snippets.

@jnewc
Last active August 21, 2025 08:55
Show Gist options
  • Select an option

  • Save jnewc/35692b2a5985c3c99e847ec56098a451 to your computer and use it in GitHub Desktop.

Select an option

Save jnewc/35692b2a5985c3c99e847ec56098a451 to your computer and use it in GitHub Desktop.
A notes app written in <100 lines of swift using SwiftUI
import SwiftUI
let dateFormatter = DateFormatter()
struct NoteItem: Codable, Hashable, Identifiable {
let id: Int
let text: String
var date = Date()
var dateText: String {
dateFormatter.dateFormat = "MMM d yyyy, h:mm a"
return dateFormatter.string(from: date)
}
}
struct ContentView : View {
@State var items: [NoteItem] = {
guard let data = UserDefaults.standard.data(forKey: "notes") else { return [] }
if let json = try? JSONDecoder().decode([NoteItem].self, from: data) {
return json
}
return []
}()
@State var taskText: String = ""
@State var showAlert = false
@State var itemToDelete: NoteItem?
var alert: Alert {
Alert(title: Text("Hey!"),
message: Text("Are you sure you want to delete this item?"),
primaryButton: .destructive(Text("Delete"), action: deleteNote),
secondaryButton: .cancel())
}
var inputView: some View {
HStack {
TextField("Write a note ...", text: $taskText)
.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
.clipped()
Button(action: didTapAddTask, label: { Text("Add") }).padding(8)
}
}
var body: some View {
VStack {
inputView
Divider()
List(items) { item in
VStack(alignment: .leading) {
Text(item.dateText).font(.headline)
Text(item.text).lineLimit(nil).multilineTextAlignment(.leading)
}
.onLongPressGesture {
self.itemToDelete = item
self.showAlert = true
}
}
.alert(isPresented: $showAlert, content: {
alert
})
}
}
func didTapAddTask() {
let id = items.reduce(0) { max($0, $1.id) } + 1
items.insert(NoteItem(id: id, text: taskText), at: 0)
taskText = ""
save()
}
func deleteNote() {
guard let itemToDelete = itemToDelete else { return }
items = items.filter { $0 != itemToDelete }
save()
}
func save() {
guard let data = try? JSONEncoder().encode(items) else { return }
UserDefaults.standard.set(data, forKey: "notes")
}
}
@whoyawn

whoyawn commented Aug 13, 2019 •

Copy link
Copy Markdown

Title should be "A notes app written in < 100 lines of swift using SwiftUI" :)

( โœ… Done, thanks @whoyawn!)

@NiklasPeterson

Copy link
Copy Markdown

Hi @jnewc :) I'm just starting to learn SwiftUI. But when I try to use your code above in a Playgrounds Project I get so many errors :/

Screenshot 2021-02-10 at 07 55 59

@SammyDerksen

SammyDerksen commented May 4, 2021 •

Copy link
Copy Markdown

Here is the Code without errors:

import SwiftUI

let dateFormatter = DateFormatter()

struct NoteItem: Codable, Hashable, Identifiable {
    let id: Int
    let text: String
    var date = Date()
    var dateText: String {
        dateFormatter.dateFormat = "MMM d yyyy, h:mm a"
        return dateFormatter.string(from: date)
    }
}

struct ContentView : View {
    @State var items: [NoteItem] = {
        guard let data = UserDefaults.standard.data(forKey: "notes") else { return [] }
        if let json = try? JSONDecoder().decode([NoteItem].self, from: data) {
            return json
        }
        return []
    }()
    
    @State var taskText: String = ""
    
    @State var showAlert = false
    
    @State var itemToDelete: NoteItem?
    
    var alert: Alert {
        Alert(title: Text("Hey!"),
              message: Text("Are you sure you want to delete this item?"),
              primaryButton: .destructive(Text("Delete"), action: deleteNote),
              secondaryButton: .cancel())
    }
    
    var inputView: some View {
        HStack {
            TextField("Write a note ...", text: $taskText)
                .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
                .clipped()
            Button(action: didTapAddTask, label: { Text("Add") }).padding(8)
        }
    }
    
    var body: some View {
        VStack {
            inputView
            Divider()
            List(items) { item in
                VStack(alignment: .leading) {
                    Text(item.dateText).font(.headline)
                    Text(item.text).lineLimit(nil).multilineTextAlignment(.leading)
                }
                .onLongPressGesture {
                    self.itemToDelete = item
                    self.showAlert = true
                }
            }
            .alert(isPresented: $showAlert, content: {
                alert
            })
        }
    }
    
    func didTapAddTask() {
        let id = items.reduce(0) { max($0, $1.id) } + 1
        items.insert(NoteItem(id: id, text: taskText), at: 0)
        taskText = ""
        save()
    }
    
    func deleteNote() {
        guard let itemToDelete = itemToDelete else { return }
        items = items.filter { $0 != itemToDelete }
        save()
    }
    
    func save() {
        guard let data = try? JSONEncoder().encode(items) else { return }
        UserDefaults.standard.set(data, forKey: "notes")
    }
}

@jnewc

jnewc commented May 4, 2021

Copy link
Copy Markdown
Author

Updated - thanks @SammyDerksen

@NiklasPeterson

Copy link
Copy Markdown

Awesome thanks @SammyDerksen for the updated version ๐Ÿ‘

And also @jnewc for sharing this to begin with ๐Ÿ˜„

@tajhans

tajhans commented Aug 24, 2021

Copy link
Copy Markdown

Here is the Code without errors:

import SwiftUI

let dateFormatter = DateFormatter()

struct NoteItem: Codable, Hashable, Identifiable {
    let id: Int
    let text: String
    var date = Date()
    var dateText: String {
        dateFormatter.dateFormat = "MMM d yyyy, h:mm a"
        return dateFormatter.string(from: date)
    }
}

struct ContentView : View {
    @State var items: [NoteItem] = {
        guard let data = UserDefaults.standard.data(forKey: "notes") else { return [] }
        if let json = try? JSONDecoder().decode([NoteItem].self, from: data) {
            return json
        }
        return []
    }()
    
    @State var taskText: String = ""
    
    @State var showAlert = false
    
    @State var itemToDelete: NoteItem?
    
    var alert: Alert {
        Alert(title: Text("Hey!"),
              message: Text("Are you sure you want to delete this item?"),
              primaryButton: .destructive(Text("Delete"), action: deleteNote),
              secondaryButton: .cancel())
    }
    
    var inputView: some View {
        HStack {
            TextField("Write a note ...", text: $taskText)
                .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
                .clipped()
            Button(action: didTapAddTask, label: { Text("Add") }).padding(8)
        }
    }
    
    var body: some View {
        VStack {
            inputView
            Divider()
            List(items) { item in
                VStack(alignment: .leading) {
                    Text(item.dateText).font(.headline)
                    Text(item.text).lineLimit(nil).multilineTextAlignment(.leading)
                }
                .onLongPressGesture {
                    self.itemToDelete = item
                    self.showAlert = true
                }
            }
            .alert(isPresented: $showAlert, content: {
                alert
            })
        }
    }
    
    func didTapAddTask() {
        let id = items.reduce(0) { max($0, $1.id) } + 1
        items.insert(NoteItem(id: id, text: taskText), at: 0)
        taskText = ""
        save()
    }
    
    func deleteNote() {
        guard let itemToDelete = itemToDelete else { return }
        items = items.filter { $0 != itemToDelete }
        save()
    }
    
    func save() {
        guard let data = try? JSONEncoder().encode(items) else { return }
        UserDefaults.standard.set(data, forKey: "notes")
    }
}

@SammyDerksen for some reason playgrounds gives me an abort error anyway to fix that?

@arrrshia

Copy link
Copy Markdown

This is incredible!

ghost commented Sep 17, 2023 •

Copy link
Copy Markdown

It helped me to improve myself in SwiftUI at the beginning. If you want to view my project: https://github.com/leparutill/Noteman/tree/main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment