Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SwiftUITodo is an example to-do list application using [SwiftUI](https://develop

## Requirements

* Xcode 11 Beta
* Xcode 11 Beta 6
* Swift 5.1

## License
Expand Down
54 changes: 27 additions & 27 deletions SwiftUITodo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,32 @@ import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {



func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}

func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

// MARK: UISceneSession Lifecycle

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

98 changes: 51 additions & 47 deletions SwiftUITodo/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,56 @@ import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

// Use a UIHostingController as window root view controller
let window = UIWindow(frame: UIScreen.main.bounds)
window.rootViewController = UIHostingController(rootView: NavigationView {
TaskListView().environmentObject(UserData())
})
self.window = window
window.makeKeyAndVisible()
}

func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}

func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}

func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}

func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}

func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}



var window: UIWindow?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

let rootView = NavigationView {
TaskListView().environmentObject(UserData())
}

// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: rootView)
self.window = window
window.makeKeyAndVisible()
}
}

func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}

func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}

func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}

func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}

func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}


}

18 changes: 9 additions & 9 deletions SwiftUITodo/Task.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
import SwiftUI

struct Task: Equatable, Hashable, Codable, Identifiable {
let id: UUID
var title: String
var isDone: Bool

init(title: String, isDone: Bool) {
self.id = UUID()
self.title = title
self.isDone = isDone
}
let id: UUID
var title: String
var isDone: Bool
init(title: String, isDone: Bool) {
self.id = UUID()
self.title = title
self.isDone = isDone
}
}
78 changes: 40 additions & 38 deletions SwiftUITodo/TaskEditView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,46 @@
import SwiftUI

struct TaskEditView: View {
@EnvironmentObject var userData: UserData
private let task: Task
private var draftTitle: State<String>
@EnvironmentObject var userData: UserData
private let task: Task
private var draftTitle: State<String>

init(task: Task) {
self.task = task
self.draftTitle = .init(initialValue: task.title)
}

var body: some View {
let inset = EdgeInsets(top: -8, leading: -10, bottom: -7, trailing: -10)
return VStack(alignment: .leading, spacing: 0) {
TextField(
self.draftTitle.binding,
placeholder: Text("Enter New Title..."),
onEditingChanged: { _ in self.updateTask() },
onCommit: {}
)
.background(
RoundedRectangle(cornerRadius: 5)
.fill(Color.clear)
.border(Color(red: 0.7, green: 0.7, blue: 0.7), width: 1 / UIScreen.main.scale, cornerRadius: 5)
.padding(inset)
)
.padding(EdgeInsets(
top: 15 - inset.top,
leading: 20 - inset.leading,
bottom: 15 - inset.bottom,
trailing: 20 - inset.trailing
))

Spacer()

init(task: Task) {
self.task = task
self.draftTitle = .init(initialValue: task.title)
}

var body: some View {
let inset = EdgeInsets(top: -8, leading: -10, bottom: -7, trailing: -10)
return VStack {
TextField(
"Enter New Title...",
text: draftTitle.projectedValue,
onEditingChanged: { _ in self.updateTask() },
onCommit: {}
)
.background(
RoundedRectangle(cornerRadius: 5)
.fill(Color.clear)
.border(Color(red: 0.7, green: 0.7, blue: 0.7), width: 1 / UIScreen.main.scale)
.cornerRadius(5)
.padding(inset)
)
.padding(EdgeInsets(
top: 15 - inset.top,
leading: 20 - inset.leading,
bottom: 15 - inset.bottom,
trailing: 20 - inset.trailing
))

Spacer()
}
.navigationBarTitle(Text("Edit Task 📝"))
}

private func updateTask() {
guard let index = self.userData.tasks.firstIndex(of: self.task) else { return }
self.userData.tasks[index].title = self.draftTitle.wrappedValue
}
.navigationBarTitle(Text("Edit Task 📝"))
}

private func updateTask() {
guard let index = self.userData.tasks.firstIndex(of: self.task) else { return }
self.userData.tasks[index].title = self.draftTitle.value
}
}
75 changes: 38 additions & 37 deletions SwiftUITodo/TaskItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,45 @@
import SwiftUI

struct TaskItemView: View {
@EnvironmentObject var userData: UserData

let task: Task
@Binding var isEditing: Bool

var body: some View {
return HStack {
if self.isEditing {
Image(systemName: "minus.circle")
.foregroundColor(.red)
.tapAction(count: 1) {
self.delete()
}
NavigationButton(destination: TaskEditView(task: task).environmentObject(self.userData)) {
Text(task.title)
}
} else {
Button(action: { self.toggleDone() }) {
Text(self.task.title)
}
Spacer()
if task.isDone {
Image(systemName: "checkmark").foregroundColor(.green)
@EnvironmentObject var userData: UserData

let task: Task
@Binding var isEditing: Bool

var body: some View {
HStack {
if self.isEditing {
Image(systemName: "minus.circle")
.foregroundColor(.red)
.onTapGesture(count: 1) {
self.delete()
}

NavigationLink(destination: TaskEditView(task: task).environmentObject(self.userData)) {
Text(task.title)
}
} else {
Button(action: { self.toggleDone() }) {
Text(self.task.title)
}
Spacer()
if task.isDone {
Image(systemName: "checkmark").foregroundColor(.green)
}
}
}
}
}
}

private func toggleDone() {
guard !self.isEditing else { return }
guard let index = self.userData.tasks.firstIndex(where: { $0.id == self.task.id }) else { return }
self.userData.tasks[index].isDone.toggle()
}

private func delete() {
self.userData.tasks.removeAll(where: { $0.id == self.task.id })
if self.userData.tasks.isEmpty {
self.isEditing = false
private func toggleDone() {
guard !self.isEditing else { return }
guard let index = self.userData.tasks.firstIndex(where: { $0.id == self.task.id }) else { return }
self.userData.tasks[index].isDone.toggle()
}
private func delete() {
self.userData.tasks.removeAll(where: { $0.id == self.task.id })
if self.userData.tasks.isEmpty {
self.isEditing = false
}
}
}
}
Loading