├── ToDoApp
├── gorevler.sqlite
├── Font
│ ├── Roboto-Bold.ttf
│ ├── Roboto-Thin.ttf
│ ├── Roboto-Black.ttf
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Light.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ ├── Roboto-BlackItalic.ttf
│ ├── Roboto-BoldItalic.ttf
│ ├── Roboto-LightItalic.ttf
│ ├── Roboto-ThinItalic.ttf
│ └── Roboto-MediumItalic.ttf
├── Assets.xcassets
│ ├── Contents.json
│ ├── User.imageset
│ │ ├── girl (5).png
│ │ └── Contents.json
│ ├── Logo.imageset
│ │ ├── What_To_Do_1.png
│ │ ├── What_To_Do_1@2x.png
│ │ ├── What_To_Do_1@3x.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── AppIcon-29.png
│ │ ├── AppIcon@2x.png
│ │ ├── AppIcon@3x.png
│ │ ├── AppIcon-20@2x.png
│ │ ├── AppIcon-20@3x.png
│ │ ├── AppIcon-29@2x.png
│ │ ├── AppIcon-29@3x.png
│ │ ├── AppIcon-40@2x.png
│ │ ├── AppIcon-40@3x.png
│ │ ├── AppIcon~ipad.png
│ │ ├── AppIcon-20~ipad.png
│ │ ├── AppIcon-29~ipad.png
│ │ ├── AppIcon-40~ipad.png
│ │ ├── AppIcon@2x~ipad.png
│ │ ├── AppIcon-20@2x~ipad.png
│ │ ├── AppIcon-29@2x~ipad.png
│ │ ├── AppIcon-40@2x~ipad.png
│ │ ├── AppIcon-60@2x~car.png
│ │ ├── AppIcon-60@3x~car.png
│ │ ├── AppIcon-83.5@2x~ipad.png
│ │ ├── AppIcon~ios-marketing.png
│ │ └── Contents.json
│ ├── UserImage.imageset
│ │ ├── UserImage.png
│ │ └── Contents.json
│ ├── Delete.imageset
│ │ ├── outline_delete_white_36pt_1x.png
│ │ └── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── ButtonColor.colorset
│ │ └── Contents.json
│ ├── PrimaryColor.colorset
│ │ └── Contents.json
│ └── TextfieldColor.colorset
│ │ └── Contents.json
├── ToDoApp-Bridging-Header.h
├── FMDB.h
├── taskadd-module
│ ├── router
│ │ └── TasAddRouter.swift
│ ├── presenter
│ │ └── TaskAddPresenter.swift
│ ├── protocols
│ │ └── TaskAddProtocols.swift
│ ├── interactor
│ │ └── TaskAddInteractor.swift
│ └── view
│ │ └── AddTaskViewController.swift
├── taskdetail-module
│ ├── router
│ │ └── TaskDetailRouter.swift
│ ├── presenter
│ │ └── TaskDetailPresenter.swift
│ ├── protocols
│ │ └── TaskDetailProtocols.swift
│ ├── interactor
│ │ └── TaskDetailInteractor.swift
│ └── view
│ │ └── TaskDetailViewController.swift
├── entity
│ └── Task.swift
├── homepage-module
│ ├── tableview
│ │ └── TaskTableViewCell.swift
│ ├── router
│ │ └── HomeRouter.swift
│ ├── presenter
│ │ └── HomePresenter.swift
│ ├── protocols
│ │ └── HomePageProtocols.swift
│ ├── interactor
│ │ └── HomeInteractor.swift
│ └── view
│ │ └── ViewController.swift
├── Info.plist
├── AppDelegate.swift
├── SceneDelegate.swift
├── Base.lproj
│ └── LaunchScreen.storyboard
├── FMDatabasePool.h
├── FMDatabaseQueue.h
├── FMDatabaseQueue.m
├── FMDatabaseAdditions.m
├── FMDatabaseAdditions.h
├── FMDatabasePool.m
├── FMResultSet.m
└── FMResultSet.h
├── ToDoApp.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── bilgecakar.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── bilgecakar.xcuserdatad
│ │ ├── xcschemes
│ │ └── xcschememanagement.plist
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
└── project.pbxproj
├── README.md
├── ToDoAppUITests
├── ToDoAppUITestsLaunchTests.swift
└── ToDoAppUITests.swift
├── LICENSE
└── ToDoAppTests
└── ToDoAppTests.swift
/ToDoApp/gorevler.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/gorevler.sqlite
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Black.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Light.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Font/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Font/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/User.imageset/girl (5).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/User.imageset/girl (5).png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1@2x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/Logo.imageset/What_To_Do_1@3x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/UserImage.imageset/UserImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/UserImage.imageset/UserImage.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/ToDoApp-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "FMDB.h"
6 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Delete.imageset/outline_delete_white_36pt_1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp/Assets.xcassets/Delete.imageset/outline_delete_white_36pt_1x.png
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/project.xcworkspace/xcuserdata/bilgecakar.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bilgecakar/ToDoAppIos/HEAD/ToDoApp.xcodeproj/project.xcworkspace/xcuserdata/bilgecakar.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ToDoApp/FMDB.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | FOUNDATION_EXPORT double FMDBVersionNumber;
4 | FOUNDATION_EXPORT const unsigned char FMDBVersionString[];
5 |
6 | #import "FMDatabase.h"
7 | #import "FMResultSet.h"
8 | #import "FMDatabaseAdditions.h"
9 | #import "FMDatabaseQueue.h"
10 | #import "FMDatabasePool.h"
11 |
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/UserImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "UserImage.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Delete.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "outline_delete_white_36pt_1x.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/xcuserdata/bilgecakar.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ToDoApp.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ToDoApp/taskadd-module/router/TasAddRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TasAddRouter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class TaskRouter : PresenterToRouterTaskAddProtocol
12 | {
13 | static func createModule(ref: AddTaskViewController) {
14 | ref.tastAddPresenterObject = TaskAddPresenter()
15 | ref.tastAddPresenterObject?.taskAddInteractor = TaskAddInteractor()
16 |
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/User.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "girl (5).png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | },
21 | "properties" : {
22 | "template-rendering-intent" : "original"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ToDoApp/taskdetail-module/router/TaskDetailRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskDetailRouter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class TaskDetailRouter : PresenterToRouterTaskDetailProtocol
11 | {
12 | static func createModule(ref: TaskDetailViewController) {
13 | ref.taskDetailIPresenterObject = TaskDetailPresenter()
14 | ref.taskDetailIPresenterObject?.taskDetailIndecator = TaskDetailInteractor()
15 | }
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/Logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "What_To_Do_1.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "What_To_Do_1@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "What_To_Do_1@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ToDoApp/taskadd-module/presenter/TaskAddPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskAddPresenter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class TaskAddPresenter : ViewToPresenterTaskAddProtocol
11 | {
12 | var taskAddInteractor: PresenterToInteractorTaskAddProtocol?
13 |
14 | func add(task_title: String, task_note: String, task_date: String) {
15 | taskAddInteractor?.addTask(task_title: task_title, task_note: task_note, task_date: task_date)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ToDoApp/taskdetail-module/presenter/TaskDetailPresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskDetailPresenter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class TaskDetailPresenter : ViewToPresenterTaskDetailProtocol
11 | {
12 | var taskDetailIndecator: PresenterToIndecatorTaskDetailProtocol?
13 |
14 | func update(task_id: Int, task_title: String, task_note: String, task_date : String) {
15 | taskDetailIndecator?.updateTask(task_id: task_id, task_title: task_title, task_note: task_note, task_date : task_date)
16 | }
17 |
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/ToDoApp/entity/Task.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Task.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 20.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class Task
11 | {
12 | var task_id : Int?
13 | var task_title : String?
14 | var task_note : String?
15 | var task_date : String?
16 |
17 | init()
18 | {
19 |
20 | }
21 |
22 | init(task_id : Int,task_title : String, task_note : String, task_date : String)
23 | {
24 | self.task_id = task_id
25 | self.task_title = task_title
26 | self.task_note = task_note
27 | self.task_date = task_date
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ToDoAppIos
2 | I developed ToDo App with Swift and Sqlite for IOS. User can add a new task and delete or update the task. In addition, user can search.
3 |
4 | ### Technologies
5 | - [x] VIPER Pattern
6 | - [x] SQLite
7 | - [x] Tableview
8 | - [x] Navigation
9 | - [x] Auto Layout
10 | - [x] Date picker
11 |
12 |
13 | ### Database
14 |
15 |
16 | ### Recording
17 | https://user-images.githubusercontent.com/36795459/160200777-b35413ce-0523-42d6-adbe-e7fabfac7d10.mp4
18 |
19 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/tableview/TaskTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskTableViewCell.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 20.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | class TaskTableViewCell: UITableViewCell {
11 |
12 | @IBOutlet weak var taskTitle: UILabel!
13 | @IBOutlet weak var dateLabel: UILabel!
14 | override func awakeFromNib() {
15 | super.awakeFromNib()
16 | // Initialization code
17 | }
18 |
19 | override func setSelected(_ selected: Bool, animated: Bool) {
20 | super.setSelected(selected, animated: animated)
21 |
22 | // Configure the view for the selected state
23 | }
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/ToDoApp/taskadd-module/protocols/TaskAddProtocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskAddProtocols.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ViewToPresenterTaskAddProtocol
11 | {
12 | var taskAddInteractor : PresenterToInteractorTaskAddProtocol? {get set}
13 |
14 | func add(task_title : String, task_note : String, task_date : String)
15 | }
16 |
17 | protocol PresenterToInteractorTaskAddProtocol
18 | {
19 | func addTask(task_title : String, task_note : String, task_date : String)
20 | }
21 |
22 | protocol PresenterToRouterTaskAddProtocol
23 | {
24 | static func createModule(ref : AddTaskViewController)
25 | }
26 |
--------------------------------------------------------------------------------
/ToDoApp/taskdetail-module/protocols/TaskDetailProtocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskDetailProtocols.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | protocol ViewToPresenterTaskDetailProtocol
11 | {
12 | var taskDetailIndecator : PresenterToIndecatorTaskDetailProtocol? {get set}
13 | func update(task_id : Int, task_title : String, task_note : String, task_date : String)
14 | }
15 |
16 | protocol PresenterToIndecatorTaskDetailProtocol
17 | {
18 | func updateTask(task_id : Int, task_title : String, task_note : String, task_date : String)
19 | }
20 |
21 | protocol PresenterToRouterTaskDetailProtocol
22 | {
23 | static func createModule(ref : TaskDetailViewController)
24 | }
25 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/router/HomeRouter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeRouter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class HomeRouter : PreseneterToRouterHomePageProtocol
12 | {
13 | static func createModule(ref: ViewController) {
14 | let presenter = HomePresenter()
15 |
16 | //View
17 | ref.homePresenterObject = presenter
18 |
19 | //Presenter
20 | ref.homePresenterObject?.homepageInteractor = HomeInteractor()
21 | ref.homePresenterObject?.homeView = ref
22 |
23 | //Interactor
24 | ref.homePresenterObject?.homepageInteractor?.homePresenter = presenter
25 |
26 |
27 |
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/ButtonColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.627",
9 | "green" : "0.659",
10 | "red" : "0.929"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/PrimaryColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.373",
9 | "green" : "0.259",
10 | "red" : "0.133"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/TextfieldColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "0.174",
8 | "blue" : "1.000",
9 | "green" : "1.000",
10 | "red" : "1.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/presenter/HomePresenter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomePresenter.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class HomePresenter : ViewToPresenterHomePageProtocol
12 | {
13 | var homepageInteractor: PresenterToInteractorHomePageProtocol?
14 |
15 | var homeView: PresenterToViewHomePageProtocol?
16 |
17 | func showTask() {
18 | homepageInteractor?.showAllTask()
19 | }
20 |
21 | func search(word: String) {
22 | homepageInteractor?.searchTask(word: word)
23 | }
24 |
25 | func delete(task_id: Int) {
26 | homepageInteractor?.deleteTask(task_id: task_id)
27 | }
28 |
29 |
30 | }
31 |
32 | extension HomePresenter : InteractorToPresenterHomePageProtocol
33 | {
34 | func sendDataToPresenter(tasks: Array) {
35 | homeView?.sendDataToView(tasks: tasks)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/ToDoAppUITests/ToDoAppUITestsLaunchTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToDoAppUITestsLaunchTests.swift
3 | // ToDoAppUITests
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import XCTest
9 |
10 | class ToDoAppUITestsLaunchTests: XCTestCase {
11 |
12 | override class var runsForEachTargetApplicationUIConfiguration: Bool {
13 | true
14 | }
15 |
16 | override func setUpWithError() throws {
17 | continueAfterFailure = false
18 | }
19 |
20 | func testLaunch() throws {
21 | let app = XCUIApplication()
22 | app.launch()
23 |
24 | // Insert steps here to perform after app launch but before taking a screenshot,
25 | // such as logging into a test account or navigating somewhere in the app
26 |
27 | let attachment = XCTAttachment(screenshot: app.screenshot())
28 | attachment.name = "Launch Screen"
29 | attachment.lifetime = .keepAlways
30 | add(attachment)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ToDoApp/taskadd-module/interactor/TaskAddInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskAddInteractor.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class TaskAddInteractor : PresenterToInteractorTaskAddProtocol
12 | {
13 | let db:FMDatabase?
14 |
15 | init(){
16 | let hedefYol = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true).first!
17 | let veritabaniURL = URL(fileURLWithPath: hedefYol).appendingPathComponent("gorevler.sqlite")
18 | db = FMDatabase(path: veritabaniURL.path)
19 | }
20 |
21 |
22 |
23 | func addTask(task_title: String, task_note: String, task_date: String) {
24 |
25 | db?.open()
26 | do{
27 | try db?.executeUpdate("INSERT INTO tasks (task_title,task_note,task_date) VALUES (?,?,?)", values: [task_title,task_note,task_date])
28 |
29 | }catch
30 | {
31 |
32 | }
33 | db?.close()
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/ToDoApp/taskdetail-module/interactor/TaskDetailInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskDetailInteractor.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 | class TaskDetailInteractor : PresenterToIndecatorTaskDetailProtocol
11 | {
12 | let db:FMDatabase?
13 |
14 | init(){
15 | let hedefYol = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true).first!
16 | let veritabaniURL = URL(fileURLWithPath: hedefYol).appendingPathComponent("gorevler.sqlite")
17 | db = FMDatabase(path: veritabaniURL.path)
18 | }
19 |
20 |
21 | func updateTask(task_id: Int, task_title: String, task_note: String, task_date : String) {
22 | db?.open()
23 | do{
24 | try db?.executeUpdate("UPDATE tasks SET task_title = ?, task_note = ?, task_date = ? WHERE task_id = ?", values: [task_title,task_note,task_date,task_id])
25 |
26 | }catch
27 | {
28 |
29 | }
30 | db?.close()
31 |
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/ToDoApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UISupportedInterfaceOrientations~iphone
6 |
7 | UIInterfaceOrientationPortrait
8 |
9 | UIAppFonts
10 |
11 | Roboto-Medium.tff
12 | Roboto-Thin.tff
13 | Roboto-Black.tff
14 |
15 | UIApplicationSceneManifest
16 |
17 | UIApplicationSupportsMultipleScenes
18 |
19 | UISceneConfigurations
20 |
21 | UIWindowSceneSessionRoleApplication
22 |
23 |
24 | UISceneConfigurationName
25 | Default Configuration
26 | UISceneDelegateClassName
27 | $(PRODUCT_MODULE_NAME).SceneDelegate
28 | UISceneStoryboardFile
29 | Main
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Bilge Çakar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/protocols/HomePageProtocols.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomePageProtocols.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | protocol PresenterToInteractorHomePageProtocol //Interactor Katmani
12 | {
13 | var homePresenter : InteractorToPresenterHomePageProtocol? {get set}
14 |
15 | func showAllTask()
16 | func searchTask(word:String)
17 | func deleteTask(task_id:Int)
18 |
19 |
20 | }
21 |
22 | protocol ViewToPresenterHomePageProtocol //Presenter Katmani
23 | {
24 | var homepageInteractor : PresenterToInteractorHomePageProtocol? {get set}
25 | var homeView : PresenterToViewHomePageProtocol? {get set}
26 |
27 | func showTask()
28 | func search(word:String)
29 | func delete(task_id:Int)
30 | }
31 |
32 |
33 |
34 | protocol InteractorToPresenterHomePageProtocol
35 | {
36 | func sendDataToPresenter(tasks : Array)
37 | }
38 |
39 | protocol PresenterToViewHomePageProtocol
40 | {
41 | func sendDataToView(tasks : Array)
42 | }
43 |
44 | protocol PreseneterToRouterHomePageProtocol
45 | {
46 | static func createModule(ref: ViewController)
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/ToDoAppTests/ToDoAppTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToDoAppTests.swift
3 | // ToDoAppTests
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import XCTest
9 | @testable import ToDoApp
10 |
11 | class ToDoAppTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | // Any test you write for XCTest can be annotated as throws and async.
25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
26 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
27 | }
28 |
29 | func testPerformanceExample() throws {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/ToDoApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | @main
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 |
13 |
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
16 | // Override point for customization after application launch.
17 | return true
18 | }
19 |
20 | // MARK: UISceneSession Lifecycle
21 |
22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
23 | // Called when a new scene session is being created.
24 | // Use this method to select a configuration to create the new scene with.
25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
26 | }
27 |
28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
29 | // Called when the user discards a scene session.
30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
32 | }
33 |
34 |
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/ToDoAppUITests/ToDoAppUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ToDoAppUITests.swift
3 | // ToDoAppUITests
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import XCTest
9 |
10 | class ToDoAppUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ToDoApp/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
11 |
12 | var window: UIWindow?
13 |
14 |
15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
19 | guard let _ = (scene as? UIWindowScene) else { return }
20 | }
21 |
22 | func sceneDidDisconnect(_ scene: UIScene) {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
27 | }
28 |
29 | func sceneDidBecomeActive(_ scene: UIScene) {
30 | // Called when the scene has moved from an inactive state to an active state.
31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
32 | }
33 |
34 | func sceneWillResignActive(_ scene: UIScene) {
35 | // Called when the scene will move from an active state to an inactive state.
36 | // This may occur due to temporary interruptions (ex. an incoming phone call).
37 | }
38 |
39 | func sceneWillEnterForeground(_ scene: UIScene) {
40 | // Called as the scene transitions from the background to the foreground.
41 | // Use this method to undo the changes made on entering the background.
42 | }
43 |
44 | func sceneDidEnterBackground(_ scene: UIScene) {
45 | // Called as the scene transitions from the foreground to the background.
46 | // Use this method to save data, release shared resources, and store enough scene-specific state information
47 | // to restore the scene back to its current state.
48 | }
49 |
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/ToDoApp/taskadd-module/view/AddTaskViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AddTaskViewController.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | class AddTaskViewController: UIViewController {
11 |
12 | @IBOutlet weak var taskNote: UITextField!
13 | @IBOutlet weak var taskDate: UIDatePicker!
14 | @IBOutlet weak var bottomView: UIView!
15 | @IBOutlet weak var titleTextfield: UITextField!
16 | @IBOutlet weak var saveButton: UIButton!
17 | @IBOutlet weak var topView: UIView!
18 |
19 | var tastAddPresenterObject : ViewToPresenterTaskAddProtocol?
20 |
21 | var dateText : String = ""
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 |
26 | TaskRouter.createModule(ref: self)
27 | updateUI()
28 |
29 | let sense = UITapGestureRecognizer(target: self, action: #selector(touchSense))
30 | view.addGestureRecognizer(sense)
31 |
32 | taskDate.addTarget(self, action: #selector(self.showDate(uiDatePicker:)), for: .valueChanged)
33 |
34 |
35 | }
36 |
37 | @objc func touchSense()
38 | {
39 | view.endEditing(true)
40 | }
41 |
42 | @objc func showDate(uiDatePicker : UIDatePicker)
43 | {
44 | let format = DateFormatter()
45 | format.dateFormat = "MMM d, yyyy"
46 | format.locale = Locale(identifier: "en")
47 | let date = format.string(from: uiDatePicker.date)
48 | print(date)
49 | dateText = date
50 |
51 | }
52 |
53 | func updateUI()
54 | {
55 | //Top view UI
56 | topView.layer.cornerRadius = 50
57 | topView.layer.maskedCorners = [.layerMinXMaxYCorner]
58 |
59 | //Temp view UI
60 | bottomView.layer.cornerRadius = 50
61 | bottomView.layer.maskedCorners = [.layerMaxXMinYCorner]
62 |
63 | //Textfield UI
64 | titleTextfield.layer.cornerRadius = 10
65 | titleTextfield.layer.masksToBounds = true
66 |
67 | //Save Button UI
68 | saveButton.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
69 | saveButton.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
70 | saveButton.layer.shadowOpacity = 1.0
71 | }
72 |
73 | @IBAction func saveData(_ sender: Any) {
74 |
75 | if let tt = titleTextfield.text, let tn = taskNote.text
76 | {
77 | tastAddPresenterObject?.add(task_title: tt, task_note: tn, task_date: dateText)
78 | }
79 |
80 | navigationController?.popToRootViewController(animated: true)
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/ToDoApp/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/interactor/HomeInteractor.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeInteractor.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | class HomeInteractor : PresenterToInteractorHomePageProtocol
12 | {
13 | var homePresenter: InteractorToPresenterHomePageProtocol?
14 |
15 | let db:FMDatabase?
16 |
17 | init(){
18 | let hedefYol = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true).first!
19 | let veritabaniURL = URL(fileURLWithPath: hedefYol).appendingPathComponent("gorevler.sqlite")
20 | db = FMDatabase(path: veritabaniURL.path)
21 | }
22 |
23 | func showAllTask() {
24 | var liste = [Task]()
25 | db?.open()
26 |
27 | do{
28 | let c = try db!.executeQuery("SELECT * FROM tasks", values: nil)
29 |
30 | while c.next() {
31 |
32 | let task_id = Int(c.string(forColumn: "task_id"))!
33 | let task_title = c.string(forColumn: "task_title")!
34 | let task_note = c.string(forColumn: "task_note")!
35 | let task_date = c.string(forColumn: "task_date")!
36 |
37 | let task = Task(task_id: task_id, task_title: task_title, task_note: task_note, task_date: task_date)
38 | liste.append(task)
39 | }
40 |
41 | homePresenter?.sendDataToPresenter(tasks: liste)
42 | }catch{
43 | print(error.localizedDescription)
44 | }
45 |
46 | db?.close()
47 | }
48 |
49 | func searchTask(word: String) {
50 | var liste = [Task]()
51 | db?.open()
52 |
53 | do{
54 | let c = try db!.executeQuery("SELECT * FROM tasks WHERE task_title like '%\(word)%'", values: nil)
55 |
56 | while c.next() {
57 | let task_id = Int(c.string(forColumn: "task_id"))!
58 | let task_title = c.string(forColumn: "task_title")!
59 | let task_note = c.string(forColumn: "task_note")!
60 | let task_date = c.string(forColumn: "task_date")!
61 |
62 | let task = Task(task_id: task_id, task_title: task_title, task_note: task_note, task_date: task_date)
63 | liste.append(task)
64 | }
65 |
66 | homePresenter?.sendDataToPresenter(tasks: liste)
67 | }catch{
68 | print(error.localizedDescription)
69 | }
70 |
71 | db?.close()
72 | }
73 |
74 | func deleteTask(task_id: Int) {
75 | db?.open()
76 |
77 | do {
78 | try db!.executeUpdate("DELETE FROM tasks WHERE task_id = ?", values: [task_id])
79 | showAllTask()
80 | }catch{
81 | print(error.localizedDescription)
82 | }
83 |
84 | db?.close()
85 | }
86 |
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/ToDoApp/taskdetail-module/view/TaskDetailViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskDetailViewController.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 21.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | class TaskDetailViewController: UIViewController {
11 |
12 | @IBOutlet weak var topView: UIView!
13 | @IBOutlet weak var taskTitle: UITextField!
14 | @IBOutlet weak var updateButton: UIButton!
15 | @IBOutlet weak var taskNote: UITextField!
16 | @IBOutlet weak var datePicker: UIDatePicker!
17 |
18 | var task : Task?
19 | var dateData : String = ""
20 | var taskDetailIPresenterObject : ViewToPresenterTaskDetailProtocol?
21 |
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 |
26 | if let t = task
27 | {
28 | taskTitle.text = t.task_title
29 | taskNote.text = t.task_note
30 | let dateFormatter = DateFormatter()
31 | dateFormatter.dateFormat = "MMM d, yyyy"
32 | dateFormatter.locale = Locale(identifier: "en")
33 | if let taskDate = dateFormatter.date(from: t.task_date!)
34 | {
35 |
36 | datePicker.date = taskDate
37 |
38 | }
39 |
40 |
41 |
42 | }
43 |
44 | TaskDetailRouter.createModule(ref: self)
45 | updateUI()
46 |
47 |
48 |
49 | datePicker.addTarget(self, action: #selector(self.showDate(uiDatePicker:)), for: .valueChanged)
50 |
51 |
52 | }
53 |
54 | @objc func touchSense()
55 | {
56 | view.endEditing(true)
57 | }
58 |
59 | @objc func showDate(uiDatePicker : UIDatePicker)
60 | {
61 | let format = DateFormatter()
62 | format.dateFormat = "MMM d, yyyy"
63 | format.locale = Locale(identifier: "en")
64 | let date = format.string(from: uiDatePicker.date)
65 | print(date)
66 | dateData = date
67 |
68 | }
69 |
70 | func updateUI()
71 | {
72 | //Top View UI
73 | topView.layer.cornerRadius = 40
74 | topView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
75 |
76 | //Circle Button UI
77 | updateButton.layer.cornerRadius = 10
78 | updateButton.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
79 | updateButton.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
80 | updateButton.layer.shadowOpacity = 1.0
81 |
82 | }
83 |
84 |
85 | @IBAction func updateData(_ sender: Any) {
86 |
87 | if let tt = taskTitle.text, let tn = taskNote.text, let t = task
88 | {
89 | taskDetailIPresenterObject?.update(task_id: t.task_id!, task_title: tt, task_note: tn, task_date: dateData )
90 | }
91 |
92 | navigationController?.popToRootViewController(animated: true)
93 | }
94 |
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/ToDoApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "AppIcon-20@2x.png",
5 | "idiom" : "iphone",
6 | "scale" : "2x",
7 | "size" : "20x20"
8 | },
9 | {
10 | "filename" : "AppIcon-20@3x.png",
11 | "idiom" : "iphone",
12 | "scale" : "3x",
13 | "size" : "20x20"
14 | },
15 | {
16 | "filename" : "AppIcon-29.png",
17 | "idiom" : "iphone",
18 | "scale" : "1x",
19 | "size" : "29x29"
20 | },
21 | {
22 | "filename" : "AppIcon-29@2x.png",
23 | "idiom" : "iphone",
24 | "scale" : "2x",
25 | "size" : "29x29"
26 | },
27 | {
28 | "filename" : "AppIcon-29@3x.png",
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "29x29"
32 | },
33 | {
34 | "filename" : "AppIcon-40@2x.png",
35 | "idiom" : "iphone",
36 | "scale" : "2x",
37 | "size" : "40x40"
38 | },
39 | {
40 | "filename" : "AppIcon-40@3x.png",
41 | "idiom" : "iphone",
42 | "scale" : "3x",
43 | "size" : "40x40"
44 | },
45 | {
46 | "filename" : "AppIcon@2x.png",
47 | "idiom" : "iphone",
48 | "scale" : "2x",
49 | "size" : "60x60"
50 | },
51 | {
52 | "filename" : "AppIcon@3x.png",
53 | "idiom" : "iphone",
54 | "scale" : "3x",
55 | "size" : "60x60"
56 | },
57 | {
58 | "filename" : "AppIcon-20~ipad.png",
59 | "idiom" : "ipad",
60 | "scale" : "1x",
61 | "size" : "20x20"
62 | },
63 | {
64 | "filename" : "AppIcon-20@2x~ipad.png",
65 | "idiom" : "ipad",
66 | "scale" : "2x",
67 | "size" : "20x20"
68 | },
69 | {
70 | "filename" : "AppIcon-29~ipad.png",
71 | "idiom" : "ipad",
72 | "scale" : "1x",
73 | "size" : "29x29"
74 | },
75 | {
76 | "filename" : "AppIcon-29@2x~ipad.png",
77 | "idiom" : "ipad",
78 | "scale" : "2x",
79 | "size" : "29x29"
80 | },
81 | {
82 | "filename" : "AppIcon-40~ipad.png",
83 | "idiom" : "ipad",
84 | "scale" : "1x",
85 | "size" : "40x40"
86 | },
87 | {
88 | "filename" : "AppIcon-40@2x~ipad.png",
89 | "idiom" : "ipad",
90 | "scale" : "2x",
91 | "size" : "40x40"
92 | },
93 | {
94 | "filename" : "AppIcon~ipad.png",
95 | "idiom" : "ipad",
96 | "scale" : "1x",
97 | "size" : "76x76"
98 | },
99 | {
100 | "filename" : "AppIcon@2x~ipad.png",
101 | "idiom" : "ipad",
102 | "scale" : "2x",
103 | "size" : "76x76"
104 | },
105 | {
106 | "filename" : "AppIcon-83.5@2x~ipad.png",
107 | "idiom" : "ipad",
108 | "scale" : "2x",
109 | "size" : "83.5x83.5"
110 | },
111 | {
112 | "filename" : "AppIcon~ios-marketing.png",
113 | "idiom" : "ios-marketing",
114 | "scale" : "1x",
115 | "size" : "1024x1024"
116 | },
117 | {
118 | "filename" : "AppIcon-60@2x~car.png",
119 | "idiom" : "car",
120 | "scale" : "2x",
121 | "size" : "60x60"
122 | },
123 | {
124 | "filename" : "AppIcon-60@3x~car.png",
125 | "idiom" : "car",
126 | "scale" : "3x",
127 | "size" : "60x60"
128 | }
129 | ],
130 | "info" : {
131 | "author" : "xcode",
132 | "version" : 1
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/ToDoApp/homepage-module/view/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // ToDoApp
4 | //
5 | // Created by Bilge Çakar on 19.03.2022.
6 | //
7 |
8 | import UIKit
9 |
10 | class ViewController: UIViewController {
11 |
12 | @IBOutlet weak var topView: UIView!
13 | @IBOutlet weak var circleButton: UIButton!
14 | @IBOutlet weak var bottomView: UIView!
15 | @IBOutlet weak var searchBar: UISearchBar!
16 | @IBOutlet weak var taskTableview: UITableView!
17 |
18 | var taskList = [Task]()
19 | var homePresenterObject : ViewToPresenterHomePageProtocol?
20 |
21 |
22 | override func viewDidLoad() {
23 | super.viewDidLoad()
24 |
25 | searchBar.delegate = self
26 | taskTableview.delegate = self
27 | taskTableview.dataSource = self
28 |
29 | updateUI()
30 | copyDatabase()
31 | HomeRouter.createModule(ref: self)
32 | }
33 |
34 | override func viewWillAppear(_ animated: Bool) {
35 | homePresenterObject?.showTask()
36 | }
37 |
38 | override func viewDidAppear(_ animated: Bool) {
39 | navigationController?.navigationBar.barStyle = .black
40 | }
41 |
42 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
43 | if segue.identifier == "toTaskDetail"
44 | {
45 | let task = sender as? Task
46 | let destinotionVC = segue.destination as! TaskDetailViewController
47 | destinotionVC.task = task
48 | }
49 | }
50 |
51 | func copyDatabase()
52 | {
53 | let bundleWay = Bundle.main.path(forResource: "gorevler", ofType: ".sqlite")
54 |
55 | let targetWay = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true).first!
56 |
57 | let coppiedWay = URL(fileURLWithPath: targetWay).appendingPathComponent("gorevler.sqlite")
58 |
59 | let fileManager = FileManager.default
60 |
61 | if fileManager.fileExists(atPath: coppiedWay.path) {
62 | print("Veritabanı zaten var.")
63 | }else{
64 | do {
65 | try fileManager.copyItem(atPath: bundleWay!, toPath: coppiedWay.path)
66 | }catch{}
67 | }
68 | }
69 |
70 | func updateUI()
71 | {
72 | //Top View UI
73 | topView.layer.cornerRadius = 50
74 | topView.layer.maskedCorners = [.layerMinXMaxYCorner]
75 |
76 | //Bottom View UI
77 | bottomView.layer.cornerRadius = 50
78 | bottomView.layer.maskedCorners = [.layerMaxXMinYCorner]
79 |
80 | //Circle Button UI
81 | circleButton.layer.cornerRadius = circleButton.frame.width / 2
82 | circleButton.layer.masksToBounds = false
83 | circleButton.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.25).cgColor
84 | circleButton.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
85 | circleButton.layer.shadowOpacity = 1.0
86 |
87 | //Searcbar UI
88 | if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
89 |
90 | textfield.backgroundColor = UIColor.white
91 | textfield.attributedPlaceholder = NSAttributedString(string: textfield.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : UIColor.black])
92 |
93 | if let leftView = textfield.leftView as? UIImageView {
94 | leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
95 | leftView.tintColor = UIColor.black
96 | }
97 |
98 | }
99 |
100 |
101 | }
102 |
103 |
104 | @IBAction func newTaskButton(_ sender: Any) {
105 |
106 | performSegue(withIdentifier: "toAddTaskPage", sender: nil)
107 | }
108 | }
109 |
110 |
111 | extension ViewController : PresenterToViewHomePageProtocol
112 | {
113 | func sendDataToView(tasks: Array) {
114 | self.taskList = tasks
115 | self.taskTableview.reloadData()
116 | }
117 |
118 |
119 | }
120 |
121 | extension ViewController : UISearchBarDelegate
122 | {
123 | func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
124 | homePresenterObject?.search(word: searchText)
125 | }
126 | }
127 |
128 |
129 | extension ViewController : UITableViewDelegate, UITableViewDataSource
130 | {
131 |
132 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
133 | return taskList.count
134 | }
135 |
136 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
137 | let task = taskList[indexPath.row]
138 | let cell = taskTableview.dequeueReusableCell(withIdentifier: "taskHucre", for: indexPath) as! TaskTableViewCell
139 |
140 | cell.taskTitle.text = "\(task.task_title!)"
141 | cell.dateLabel.text = "\(task.task_date!)"
142 |
143 | return cell
144 | }
145 |
146 |
147 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
148 | let task = taskList[indexPath.row]
149 | performSegue(withIdentifier: "toTaskDetail", sender: task)
150 | taskTableview.deselectRow(at: indexPath, animated: true)
151 | }
152 |
153 |
154 | func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
155 |
156 | let deleteAction = UIContextualAction(style: .destructive, title: ""){(contextualAction,view,bool) in
157 | let task = self.taskList[indexPath.row]
158 |
159 | let alert = UIAlertController(title: "Are you sure want to delete \(task.task_title!)?", message: "You cannot undo this action", preferredStyle: .alert)
160 |
161 | let cancelAction = UIAlertAction(title: "Cancel", style: .cancel){ action in }
162 | alert.addAction(cancelAction)
163 |
164 | let yesAction = UIAlertAction(title: "Yes", style: .destructive){ action in
165 | self.homePresenterObject?.delete(task_id: task.task_id!)
166 | }
167 | alert.addAction(yesAction)
168 |
169 | self.present(alert, animated: true)
170 | }
171 | deleteAction.backgroundColor = UIColor(named: "ButtonColor")
172 | deleteAction.image = UIImage(named: "Delete.png")
173 |
174 |
175 | return UISwipeActionsConfiguration(actions: [deleteAction])
176 |
177 | }
178 | }
179 |
180 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabasePool.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabasePool.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class FMDatabase;
12 |
13 | /** Pool of `` objects.
14 |
15 | ### See also
16 |
17 | - ``
18 | - ``
19 |
20 | @warning Before using `FMDatabasePool`, please consider using `` instead.
21 |
22 | If you really really really know what you're doing and `FMDatabasePool` is what
23 | you really really need (ie, you're using a read only database), OK you can use
24 | it. But just be careful not to deadlock!
25 |
26 | For an example on deadlocking, search for:
27 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD`
28 | in the main.m file.
29 | */
30 |
31 | @interface FMDatabasePool : NSObject {
32 | NSString *_path;
33 |
34 | dispatch_queue_t _lockQueue;
35 |
36 | NSMutableArray *_databaseInPool;
37 | NSMutableArray *_databaseOutPool;
38 |
39 | __unsafe_unretained id _delegate;
40 |
41 | NSUInteger _maximumNumberOfDatabasesToCreate;
42 | int _openFlags;
43 | NSString *_vfsName;
44 | }
45 |
46 | /** Database path */
47 |
48 | @property (atomic, retain) NSString *path;
49 |
50 | /** Delegate object */
51 |
52 | @property (atomic, assign) id delegate;
53 |
54 | /** Maximum number of databases to create */
55 |
56 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate;
57 |
58 | /** Open flags */
59 |
60 | @property (atomic, readonly) int openFlags;
61 |
62 | /** Custom virtual file system name */
63 |
64 | @property (atomic, copy) NSString *vfsName;
65 |
66 |
67 | ///---------------------
68 | /// @name Initialization
69 | ///---------------------
70 |
71 | /** Create pool using path.
72 |
73 | @param aPath The file path of the database.
74 |
75 | @return The `FMDatabasePool` object. `nil` on error.
76 | */
77 |
78 | + (instancetype)databasePoolWithPath:(NSString*)aPath;
79 |
80 | /** Create pool using path and specified flags
81 |
82 | @param aPath The file path of the database.
83 | @param openFlags Flags passed to the openWithFlags method of the database
84 |
85 | @return The `FMDatabasePool` object. `nil` on error.
86 | */
87 |
88 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags;
89 |
90 | /** Create pool using path.
91 |
92 | @param aPath The file path of the database.
93 |
94 | @return The `FMDatabasePool` object. `nil` on error.
95 | */
96 |
97 | - (instancetype)initWithPath:(NSString*)aPath;
98 |
99 | /** Create pool using path and specified flags.
100 |
101 | @param aPath The file path of the database.
102 | @param openFlags Flags passed to the openWithFlags method of the database
103 |
104 | @return The `FMDatabasePool` object. `nil` on error.
105 | */
106 |
107 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
108 |
109 | /** Create pool using path and specified flags.
110 |
111 | @param aPath The file path of the database.
112 | @param openFlags Flags passed to the openWithFlags method of the database
113 | @param vfsName The name of a custom virtual file system
114 |
115 | @return The `FMDatabasePool` object. `nil` on error.
116 | */
117 |
118 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName;
119 |
120 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
121 |
122 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass.
123 |
124 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
125 | */
126 |
127 | + (Class)databaseClass;
128 |
129 | ///------------------------------------------------
130 | /// @name Keeping track of checked in/out databases
131 | ///------------------------------------------------
132 |
133 | /** Number of checked-in databases in pool
134 |
135 | @returns Number of databases
136 | */
137 |
138 | - (NSUInteger)countOfCheckedInDatabases;
139 |
140 | /** Number of checked-out databases in pool
141 |
142 | @returns Number of databases
143 | */
144 |
145 | - (NSUInteger)countOfCheckedOutDatabases;
146 |
147 | /** Total number of databases in pool
148 |
149 | @returns Number of databases
150 | */
151 |
152 | - (NSUInteger)countOfOpenDatabases;
153 |
154 | /** Release all databases in pool */
155 |
156 | - (void)releaseAllDatabases;
157 |
158 | ///------------------------------------------
159 | /// @name Perform database operations in pool
160 | ///------------------------------------------
161 |
162 | /** Synchronously perform database operations in pool.
163 |
164 | @param block The code to be run on the `FMDatabasePool` pool.
165 | */
166 |
167 | - (void)inDatabase:(void (^)(FMDatabase *db))block;
168 |
169 | /** Synchronously perform database operations in pool using transaction.
170 |
171 | @param block The code to be run on the `FMDatabasePool` pool.
172 | */
173 |
174 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
175 |
176 | /** Synchronously perform database operations in pool using deferred transaction.
177 |
178 | @param block The code to be run on the `FMDatabasePool` pool.
179 | */
180 |
181 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
182 |
183 | /** Synchronously perform database operations in pool using save point.
184 |
185 | @param block The code to be run on the `FMDatabasePool` pool.
186 |
187 | @return `NSError` object if error; `nil` if successful.
188 |
189 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead.
190 | */
191 |
192 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
193 |
194 | @end
195 |
196 |
197 | /** FMDatabasePool delegate category
198 |
199 | This is a category that defines the protocol for the FMDatabasePool delegate
200 | */
201 |
202 | @interface NSObject (FMDatabasePoolDelegate)
203 |
204 | /** Asks the delegate whether database should be added to the pool.
205 |
206 | @param pool The `FMDatabasePool` object.
207 | @param database The `FMDatabase` object.
208 |
209 | @return `YES` if it should add database to pool; `NO` if not.
210 |
211 | */
212 |
213 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database;
214 |
215 | /** Tells the delegate that database was added to the pool.
216 |
217 | @param pool The `FMDatabasePool` object.
218 | @param database The `FMDatabase` object.
219 |
220 | */
221 |
222 | - (void)databasePool:(FMDatabasePool*)pool didAddDatabase:(FMDatabase*)database;
223 |
224 | @end
225 |
226 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabaseQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class FMDatabase;
12 |
13 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`.
14 |
15 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time.
16 |
17 | Instead, use `FMDatabaseQueue`. Here's how to use it:
18 |
19 | First, make your queue.
20 |
21 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];
22 |
23 | Then use it like so:
24 |
25 | [queue inDatabase:^(FMDatabase *db) {
26 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
29 |
30 | FMResultSet *rs = [db executeQuery:@"select * from foo"];
31 | while ([rs next]) {
32 | //…
33 | }
34 | }];
35 |
36 | An easy way to wrap things up in a transaction can be done like this:
37 |
38 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
39 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
42 |
43 | if (whoopsSomethingWrongHappened) {
44 | *rollback = YES;
45 | return;
46 | }
47 | // etc…
48 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
49 | }];
50 |
51 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy.
52 |
53 | ### See also
54 |
55 | - ``
56 |
57 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead.
58 |
59 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread.
60 |
61 | */
62 |
63 | @interface FMDatabaseQueue : NSObject {
64 | NSString *_path;
65 | dispatch_queue_t _queue;
66 | FMDatabase *_db;
67 | int _openFlags;
68 | NSString *_vfsName;
69 | }
70 |
71 | /** Path of database */
72 |
73 | @property (atomic, retain) NSString *path;
74 |
75 | /** Open flags */
76 |
77 | @property (atomic, readonly) int openFlags;
78 |
79 | /** Custom virtual file system name */
80 |
81 | @property (atomic, copy) NSString *vfsName;
82 |
83 | ///----------------------------------------------------
84 | /// @name Initialization, opening, and closing of queue
85 | ///----------------------------------------------------
86 |
87 | /** Create queue using path.
88 |
89 | @param aPath The file path of the database.
90 |
91 | @return The `FMDatabaseQueue` object. `nil` on error.
92 | */
93 |
94 | + (instancetype)databaseQueueWithPath:(NSString*)aPath;
95 |
96 | /** Create queue using path and specified flags.
97 |
98 | @param aPath The file path of the database.
99 | @param openFlags Flags passed to the openWithFlags method of the database
100 |
101 | @return The `FMDatabaseQueue` object. `nil` on error.
102 | */
103 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags;
104 |
105 | /** Create queue using path.
106 |
107 | @param aPath The file path of the database.
108 |
109 | @return The `FMDatabaseQueue` object. `nil` on error.
110 | */
111 |
112 | - (instancetype)initWithPath:(NSString*)aPath;
113 |
114 | /** Create queue using path and specified flags.
115 |
116 | @param aPath The file path of the database.
117 | @param openFlags Flags passed to the openWithFlags method of the database
118 |
119 | @return The `FMDatabaseQueue` object. `nil` on error.
120 | */
121 |
122 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags;
123 |
124 | /** Create queue using path and specified flags.
125 |
126 | @param aPath The file path of the database.
127 | @param openFlags Flags passed to the openWithFlags method of the database
128 | @param vfsName The name of a custom virtual file system
129 |
130 | @return The `FMDatabaseQueue` object. `nil` on error.
131 | */
132 |
133 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName;
134 |
135 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object.
136 |
137 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass.
138 |
139 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object.
140 | */
141 |
142 | + (Class)databaseClass;
143 |
144 | /** Close database used by queue. */
145 |
146 | - (void)close;
147 |
148 | /** Interupt pending database operation. */
149 |
150 | - (void)interrupt;
151 |
152 | ///-----------------------------------------------
153 | /// @name Dispatching database operations to queue
154 | ///-----------------------------------------------
155 |
156 | /** Synchronously perform database operations on queue.
157 |
158 | @param block The code to be run on the queue of `FMDatabaseQueue`
159 | */
160 |
161 | - (void)inDatabase:(void (^)(FMDatabase *db))block;
162 |
163 | /** Synchronously perform database operations on queue, using transactions.
164 |
165 | @param block The code to be run on the queue of `FMDatabaseQueue`
166 | */
167 |
168 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
169 |
170 | /** Synchronously perform database operations on queue, using deferred transactions.
171 |
172 | @param block The code to be run on the queue of `FMDatabaseQueue`
173 | */
174 |
175 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block;
176 |
177 | ///-----------------------------------------------
178 | /// @name Dispatching database operations to queue
179 | ///-----------------------------------------------
180 |
181 | /** Synchronously perform database operations using save point.
182 |
183 | @param block The code to be run on the queue of `FMDatabaseQueue`
184 | */
185 |
186 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock.
187 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead.
188 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block;
189 |
190 | @end
191 |
192 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabaseQueue.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseQueue.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #import "FMDatabaseQueue.h"
10 | #import "FMDatabase.h"
11 |
12 | #if FMDB_SQLITE_STANDALONE
13 | #import
14 | #else
15 | #import
16 | #endif
17 |
18 | /*
19 |
20 | Note: we call [self retain]; before using dispatch_sync, just incase
21 | FMDatabaseQueue is released on another thread and we're in the middle of doing
22 | something in dispatch_sync
23 |
24 | */
25 |
26 | /*
27 | * A key used to associate the FMDatabaseQueue object with the dispatch_queue_t it uses.
28 | * This in turn is used for deadlock detection by seeing if inDatabase: is called on
29 | * the queue's dispatch queue, which should not happen and causes a deadlock.
30 | */
31 | static const void * const kDispatchQueueSpecificKey = &kDispatchQueueSpecificKey;
32 |
33 | @implementation FMDatabaseQueue
34 |
35 | @synthesize path = _path;
36 | @synthesize openFlags = _openFlags;
37 | @synthesize vfsName = _vfsName;
38 |
39 | + (instancetype)databaseQueueWithPath:(NSString*)aPath {
40 |
41 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath];
42 |
43 | FMDBAutorelease(q);
44 |
45 | return q;
46 | }
47 |
48 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags {
49 |
50 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags];
51 |
52 | FMDBAutorelease(q);
53 |
54 | return q;
55 | }
56 |
57 | + (Class)databaseClass {
58 | return [FMDatabase class];
59 | }
60 |
61 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
62 |
63 | self = [super init];
64 |
65 | if (self != nil) {
66 |
67 | _db = [[[self class] databaseClass] databaseWithPath:aPath];
68 | FMDBRetain(_db);
69 |
70 | #if SQLITE_VERSION_NUMBER >= 3005000
71 | BOOL success = [_db openWithFlags:openFlags vfs:vfsName];
72 | #else
73 | BOOL success = [_db open];
74 | #endif
75 | if (!success) {
76 | NSLog(@"Could not create database queue for path %@", aPath);
77 | FMDBRelease(self);
78 | return 0x00;
79 | }
80 |
81 | _path = FMDBReturnRetained(aPath);
82 |
83 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
84 | dispatch_queue_set_specific(_queue, kDispatchQueueSpecificKey, (__bridge void *)self, NULL);
85 | _openFlags = openFlags;
86 | _vfsName = [vfsName copy];
87 | }
88 |
89 | return self;
90 | }
91 |
92 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
93 | return [self initWithPath:aPath flags:openFlags vfs:nil];
94 | }
95 |
96 | - (instancetype)initWithPath:(NSString*)aPath {
97 |
98 | // default flags for sqlite3_open
99 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE vfs:nil];
100 | }
101 |
102 | - (instancetype)init {
103 | return [self initWithPath:nil];
104 | }
105 |
106 |
107 | - (void)dealloc {
108 |
109 | FMDBRelease(_db);
110 | FMDBRelease(_path);
111 |
112 | if (_queue) {
113 | FMDBDispatchQueueRelease(_queue);
114 | _queue = 0x00;
115 | }
116 | #if ! __has_feature(objc_arc)
117 | [super dealloc];
118 | #endif
119 | }
120 |
121 | - (void)close {
122 | FMDBRetain(self);
123 | dispatch_sync(_queue, ^() {
124 | [self->_db close];
125 | FMDBRelease(_db);
126 | self->_db = 0x00;
127 | });
128 | FMDBRelease(self);
129 | }
130 |
131 | - (void)interrupt
132 | {
133 | [[self database] interrupt];
134 | }
135 |
136 | - (FMDatabase*)database {
137 | if (!_db) {
138 | _db = FMDBReturnRetained([[[self class] databaseClass] databaseWithPath:_path]);
139 |
140 | #if SQLITE_VERSION_NUMBER >= 3005000
141 | BOOL success = [_db openWithFlags:_openFlags vfs:_vfsName];
142 | #else
143 | BOOL success = [_db open];
144 | #endif
145 | if (!success) {
146 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path);
147 | FMDBRelease(_db);
148 | _db = 0x00;
149 | return 0x00;
150 | }
151 | }
152 |
153 | return _db;
154 | }
155 |
156 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
157 | #ifndef NDEBUG
158 | /* Get the currently executing queue (which should probably be nil, but in theory could be another DB queue
159 | * and then check it against self to make sure we're not about to deadlock. */
160 | FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
161 | assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
162 | #endif
163 |
164 | FMDBRetain(self);
165 |
166 | dispatch_sync(_queue, ^() {
167 |
168 | FMDatabase *db = [self database];
169 | block(db);
170 |
171 | if ([db hasOpenResultSets]) {
172 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
173 |
174 | #if defined(DEBUG) && DEBUG
175 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);
176 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
177 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
178 | NSLog(@"query: '%@'", [rs query]);
179 | }
180 | #endif
181 | }
182 | });
183 |
184 | FMDBRelease(self);
185 | }
186 |
187 |
188 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
189 | FMDBRetain(self);
190 | dispatch_sync(_queue, ^() {
191 |
192 | BOOL shouldRollback = NO;
193 |
194 | if (useDeferred) {
195 | [[self database] beginDeferredTransaction];
196 | }
197 | else {
198 | [[self database] beginTransaction];
199 | }
200 |
201 | block([self database], &shouldRollback);
202 |
203 | if (shouldRollback) {
204 | [[self database] rollback];
205 | }
206 | else {
207 | [[self database] commit];
208 | }
209 | });
210 |
211 | FMDBRelease(self);
212 | }
213 |
214 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
215 | [self beginTransaction:YES withBlock:block];
216 | }
217 |
218 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
219 | [self beginTransaction:NO withBlock:block];
220 | }
221 |
222 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
223 | #if SQLITE_VERSION_NUMBER >= 3007000
224 | static unsigned long savePointIdx = 0;
225 | __block NSError *err = 0x00;
226 | FMDBRetain(self);
227 | dispatch_sync(_queue, ^() {
228 |
229 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
230 |
231 | BOOL shouldRollback = NO;
232 |
233 | if ([[self database] startSavePointWithName:name error:&err]) {
234 |
235 | block([self database], &shouldRollback);
236 |
237 | if (shouldRollback) {
238 | // We need to rollback and release this savepoint to remove it
239 | [[self database] rollbackToSavePointWithName:name error:&err];
240 | }
241 | [[self database] releaseSavePointWithName:name error:&err];
242 |
243 | }
244 | });
245 | FMDBRelease(self);
246 | return err;
247 | #else
248 | NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil);
249 | if (self.logsErrors) NSLog(@"%@", errorMessage);
250 | return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
251 | #endif
252 | }
253 |
254 | @end
255 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabaseAdditions.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import "FMDatabase.h"
10 | #import "FMDatabaseAdditions.h"
11 | #import "TargetConditionals.h"
12 |
13 | #if FMDB_SQLITE_STANDALONE
14 | #import
15 | #else
16 | #import
17 | #endif
18 |
19 | @interface FMDatabase (PrivateStuff)
20 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args;
21 | @end
22 |
23 | @implementation FMDatabase (FMDatabaseAdditions)
24 |
25 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
26 | va_list args; \
27 | va_start(args, query); \
28 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \
29 | va_end(args); \
30 | if (![resultSet next]) { return (type)0; } \
31 | type ret = [resultSet sel:0]; \
32 | [resultSet close]; \
33 | [resultSet setParentDB:nil]; \
34 | return ret;
35 |
36 |
37 | - (NSString*)stringForQuery:(NSString*)query, ... {
38 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex);
39 | }
40 |
41 | - (int)intForQuery:(NSString*)query, ... {
42 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex);
43 | }
44 |
45 | - (long)longForQuery:(NSString*)query, ... {
46 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex);
47 | }
48 |
49 | - (BOOL)boolForQuery:(NSString*)query, ... {
50 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex);
51 | }
52 |
53 | - (double)doubleForQuery:(NSString*)query, ... {
54 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex);
55 | }
56 |
57 | - (NSData*)dataForQuery:(NSString*)query, ... {
58 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
59 | }
60 |
61 | - (NSDate*)dateForQuery:(NSString*)query, ... {
62 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
63 | }
64 |
65 |
66 | - (BOOL)tableExists:(NSString*)tableName {
67 |
68 | tableName = [tableName lowercaseString];
69 |
70 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
71 |
72 | //if at least one next exists, table exists
73 | BOOL returnBool = [rs next];
74 |
75 | //close and free object
76 | [rs close];
77 |
78 | return returnBool;
79 | }
80 |
81 | /*
82 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
83 | check if table exist in database (patch from OZLB)
84 | */
85 | - (FMResultSet*)getSchema {
86 |
87 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
88 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
89 |
90 | return rs;
91 | }
92 |
93 | /*
94 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
95 | */
96 | - (FMResultSet*)getTableSchema:(NSString*)tableName {
97 |
98 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
99 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"pragma table_info('%@')", tableName]];
100 |
101 | return rs;
102 | }
103 |
104 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName {
105 |
106 | BOOL returnBool = NO;
107 |
108 | tableName = [tableName lowercaseString];
109 | columnName = [columnName lowercaseString];
110 |
111 | FMResultSet *rs = [self getTableSchema:tableName];
112 |
113 | //check if column is present in table schema
114 | while ([rs next]) {
115 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) {
116 | returnBool = YES;
117 | break;
118 | }
119 | }
120 |
121 | //If this is not done FMDatabase instance stays out of pool
122 | [rs close];
123 |
124 | return returnBool;
125 | }
126 |
127 |
128 |
129 | - (uint32_t)applicationID {
130 | #if SQLITE_VERSION_NUMBER >= 3007017
131 | uint32_t r = 0;
132 |
133 | FMResultSet *rs = [self executeQuery:@"pragma application_id"];
134 |
135 | if ([rs next]) {
136 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
137 | }
138 |
139 | [rs close];
140 |
141 | return r;
142 | #else
143 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
144 | if (self.logsErrors) NSLog(@"%@", errorMessage);
145 | return 0;
146 | #endif
147 | }
148 |
149 | - (void)setApplicationID:(uint32_t)appID {
150 | #if SQLITE_VERSION_NUMBER >= 3007017
151 | NSString *query = [NSString stringWithFormat:@"pragma application_id=%d", appID];
152 | FMResultSet *rs = [self executeQuery:query];
153 | [rs next];
154 | [rs close];
155 | #else
156 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
157 | if (self.logsErrors) NSLog(@"%@", errorMessage);
158 | #endif
159 | }
160 |
161 |
162 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
163 |
164 | - (NSString*)applicationIDString {
165 | #if SQLITE_VERSION_NUMBER >= 3007017
166 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]);
167 |
168 | assert([s length] == 6);
169 |
170 | s = [s substringWithRange:NSMakeRange(1, 4)];
171 |
172 |
173 | return s;
174 | #else
175 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
176 | if (self.logsErrors) NSLog(@"%@", errorMessage);
177 | return nil;
178 | #endif
179 | }
180 |
181 | - (void)setApplicationIDString:(NSString*)s {
182 | #if SQLITE_VERSION_NUMBER >= 3007017
183 | if ([s length] != 4) {
184 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]);
185 | }
186 |
187 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])];
188 | #else
189 | NSString *errorMessage = NSLocalizedString(@"Application ID functions require SQLite 3.7.17", nil);
190 | if (self.logsErrors) NSLog(@"%@", errorMessage);
191 | #endif
192 | }
193 |
194 | #endif
195 |
196 | - (uint32_t)userVersion {
197 | uint32_t r = 0;
198 |
199 | FMResultSet *rs = [self executeQuery:@"pragma user_version"];
200 |
201 | if ([rs next]) {
202 | r = (uint32_t)[rs longLongIntForColumnIndex:0];
203 | }
204 |
205 | [rs close];
206 | return r;
207 | }
208 |
209 | - (void)setUserVersion:(uint32_t)version {
210 | NSString *query = [NSString stringWithFormat:@"pragma user_version = %d", version];
211 | FMResultSet *rs = [self executeQuery:query];
212 | [rs next];
213 | [rs close];
214 | }
215 |
216 | #pragma clang diagnostic push
217 | #pragma clang diagnostic ignored "-Wdeprecated-implementations"
218 |
219 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) {
220 | return [self columnExists:columnName inTableWithName:tableName];
221 | }
222 |
223 | #pragma clang diagnostic pop
224 |
225 |
226 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error {
227 | sqlite3_stmt *pStmt = NULL;
228 | BOOL validationSucceeded = YES;
229 |
230 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
231 | if (rc != SQLITE_OK) {
232 | validationSucceeded = NO;
233 | if (error) {
234 | *error = [NSError errorWithDomain:NSCocoaErrorDomain
235 | code:[self lastErrorCode]
236 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage]
237 | forKey:NSLocalizedDescriptionKey]];
238 | }
239 | }
240 |
241 | sqlite3_finalize(pStmt);
242 |
243 | return validationSucceeded;
244 | }
245 |
246 | @end
247 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabaseAdditions.h:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabaseAdditions.h
3 | // fmdb
4 | //
5 | // Created by August Mueller on 10/30/05.
6 | // Copyright 2005 Flying Meat Inc.. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "FMDatabase.h"
11 |
12 |
13 | /** Category of additions for `` class.
14 |
15 | ### See also
16 |
17 | - ``
18 | */
19 |
20 | @interface FMDatabase (FMDatabaseAdditions)
21 |
22 | ///----------------------------------------
23 | /// @name Return results of SQL to variable
24 | ///----------------------------------------
25 |
26 | /** Return `int` value for query
27 |
28 | @param query The SQL query to be performed.
29 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
30 |
31 | @return `int` value.
32 |
33 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
34 | */
35 |
36 | - (int)intForQuery:(NSString*)query, ...;
37 |
38 | /** Return `long` value for query
39 |
40 | @param query The SQL query to be performed.
41 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
42 |
43 | @return `long` value.
44 |
45 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
46 | */
47 |
48 | - (long)longForQuery:(NSString*)query, ...;
49 |
50 | /** Return `BOOL` value for query
51 |
52 | @param query The SQL query to be performed.
53 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
54 |
55 | @return `BOOL` value.
56 |
57 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
58 | */
59 |
60 | - (BOOL)boolForQuery:(NSString*)query, ...;
61 |
62 | /** Return `double` value for query
63 |
64 | @param query The SQL query to be performed.
65 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
66 |
67 | @return `double` value.
68 |
69 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
70 | */
71 |
72 | - (double)doubleForQuery:(NSString*)query, ...;
73 |
74 | /** Return `NSString` value for query
75 |
76 | @param query The SQL query to be performed.
77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
78 |
79 | @return `NSString` value.
80 |
81 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
82 | */
83 |
84 | - (NSString*)stringForQuery:(NSString*)query, ...;
85 |
86 | /** Return `NSData` value for query
87 |
88 | @param query The SQL query to be performed.
89 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
90 |
91 | @return `NSData` value.
92 |
93 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
94 | */
95 |
96 | - (NSData*)dataForQuery:(NSString*)query, ...;
97 |
98 | /** Return `NSDate` value for query
99 |
100 | @param query The SQL query to be performed.
101 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query.
102 |
103 | @return `NSDate` value.
104 |
105 | @note To use this method from Swift, you must include `FMDatabaseAdditionsVariadic.swift` in your project.
106 | */
107 |
108 | - (NSDate*)dateForQuery:(NSString*)query, ...;
109 |
110 |
111 | // Notice that there's no dataNoCopyForQuery:.
112 | // That would be a bad idea, because we close out the result set, and then what
113 | // happens to the data that we just didn't copy? Who knows, not I.
114 |
115 |
116 | ///--------------------------------
117 | /// @name Schema related operations
118 | ///--------------------------------
119 |
120 | /** Does table exist in database?
121 |
122 | @param tableName The name of the table being looked for.
123 |
124 | @return `YES` if table found; `NO` if not found.
125 | */
126 |
127 | - (BOOL)tableExists:(NSString*)tableName;
128 |
129 | /** The schema of the database.
130 |
131 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields:
132 |
133 | - `type` - The type of entity (e.g. table, index, view, or trigger)
134 | - `name` - The name of the object
135 | - `tbl_name` - The name of the table to which the object references
136 | - `rootpage` - The page number of the root b-tree page for tables and indices
137 | - `sql` - The SQL that created the entity
138 |
139 | @return `FMResultSet` of schema; `nil` on error.
140 |
141 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html)
142 | */
143 |
144 | - (FMResultSet*)getSchema;
145 |
146 | /** The schema of the database.
147 |
148 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example:
149 |
150 | PRAGMA table_info('employees')
151 |
152 | This will report:
153 |
154 | - `cid` - The column ID number
155 | - `name` - The name of the column
156 | - `type` - The data type specified for the column
157 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required)
158 | - `dflt_value` - The default value for the column
159 | - `pk` - Whether the field is part of the primary key of the table
160 |
161 | @param tableName The name of the table for whom the schema will be returned.
162 |
163 | @return `FMResultSet` of schema; `nil` on error.
164 |
165 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info)
166 | */
167 |
168 | - (FMResultSet*)getTableSchema:(NSString*)tableName;
169 |
170 | /** Test to see if particular column exists for particular table in database
171 |
172 | @param columnName The name of the column.
173 |
174 | @param tableName The name of the table.
175 |
176 | @return `YES` if column exists in table in question; `NO` otherwise.
177 | */
178 |
179 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName;
180 |
181 | /** Test to see if particular column exists for particular table in database
182 |
183 | @param columnName The name of the column.
184 |
185 | @param tableName The name of the table.
186 |
187 | @return `YES` if column exists in table in question; `NO` otherwise.
188 |
189 | @see columnExists:inTableWithName:
190 |
191 | @warning Deprecated - use `` instead.
192 | */
193 |
194 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated));
195 |
196 |
197 | /** Validate SQL statement
198 |
199 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`.
200 |
201 | @param sql The SQL statement being validated.
202 |
203 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned.
204 |
205 | @return `YES` if validation succeeded without incident; `NO` otherwise.
206 |
207 | */
208 |
209 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error;
210 |
211 |
212 | ///-----------------------------------
213 | /// @name Application identifier tasks
214 | ///-----------------------------------
215 |
216 | /** Retrieve application ID
217 |
218 | @return The `uint32_t` numeric value of the application ID.
219 |
220 | @see setApplicationID:
221 | */
222 |
223 | - (uint32_t)applicationID;
224 |
225 | /** Set the application ID
226 |
227 | @param appID The `uint32_t` numeric value of the application ID.
228 |
229 | @see applicationID
230 | */
231 |
232 | - (void)setApplicationID:(uint32_t)appID;
233 |
234 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE
235 | /** Retrieve application ID string
236 |
237 | @return The `NSString` value of the application ID.
238 |
239 | @see setApplicationIDString:
240 | */
241 |
242 |
243 | - (NSString*)applicationIDString;
244 |
245 | /** Set the application ID string
246 |
247 | @param string The `NSString` value of the application ID.
248 |
249 | @see applicationIDString
250 | */
251 |
252 | - (void)setApplicationIDString:(NSString*)string;
253 |
254 | #endif
255 |
256 | ///-----------------------------------
257 | /// @name user version identifier tasks
258 | ///-----------------------------------
259 |
260 | /** Retrieve user version
261 |
262 | @return The `uint32_t` numeric value of the user version.
263 |
264 | @see setUserVersion:
265 | */
266 |
267 | - (uint32_t)userVersion;
268 |
269 | /** Set the user-version
270 |
271 | @param version The `uint32_t` numeric value of the user version.
272 |
273 | @see userVersion
274 | */
275 |
276 | - (void)setUserVersion:(uint32_t)version;
277 |
278 | @end
279 |
--------------------------------------------------------------------------------
/ToDoApp/FMDatabasePool.m:
--------------------------------------------------------------------------------
1 | //
2 | // FMDatabasePool.m
3 | // fmdb
4 | //
5 | // Created by August Mueller on 6/22/11.
6 | // Copyright 2011 Flying Meat Inc. All rights reserved.
7 | //
8 |
9 | #if FMDB_SQLITE_STANDALONE
10 | #import
11 | #else
12 | #import
13 | #endif
14 |
15 | #import "FMDatabasePool.h"
16 | #import "FMDatabase.h"
17 |
18 | @interface FMDatabasePool()
19 |
20 | - (void)pushDatabaseBackInPool:(FMDatabase*)db;
21 | - (FMDatabase*)db;
22 |
23 | @end
24 |
25 |
26 | @implementation FMDatabasePool
27 | @synthesize path=_path;
28 | @synthesize delegate=_delegate;
29 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate;
30 | @synthesize openFlags=_openFlags;
31 |
32 |
33 | + (instancetype)databasePoolWithPath:(NSString*)aPath {
34 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]);
35 | }
36 |
37 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags {
38 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]);
39 | }
40 |
41 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags vfs:(NSString *)vfsName {
42 |
43 | self = [super init];
44 |
45 | if (self != nil) {
46 | _path = [aPath copy];
47 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL);
48 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]);
49 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]);
50 | _openFlags = openFlags;
51 | _vfsName = [vfsName copy];
52 | }
53 |
54 | return self;
55 | }
56 |
57 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags {
58 | return [self initWithPath:aPath flags:openFlags vfs:nil];
59 | }
60 |
61 | - (instancetype)initWithPath:(NSString*)aPath
62 | {
63 | // default flags for sqlite3_open
64 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE];
65 | }
66 |
67 | - (instancetype)init {
68 | return [self initWithPath:nil];
69 | }
70 |
71 | + (Class)databaseClass {
72 | return [FMDatabase class];
73 | }
74 |
75 | - (void)dealloc {
76 |
77 | _delegate = 0x00;
78 | FMDBRelease(_path);
79 | FMDBRelease(_databaseInPool);
80 | FMDBRelease(_databaseOutPool);
81 |
82 | if (_lockQueue) {
83 | FMDBDispatchQueueRelease(_lockQueue);
84 | _lockQueue = 0x00;
85 | }
86 | #if ! __has_feature(objc_arc)
87 | [super dealloc];
88 | #endif
89 | }
90 |
91 |
92 | - (void)executeLocked:(void (^)(void))aBlock {
93 | dispatch_sync(_lockQueue, aBlock);
94 | }
95 |
96 | - (void)pushDatabaseBackInPool:(FMDatabase*)db {
97 |
98 | if (!db) { // db can be null if we set an upper bound on the # of databases to create.
99 | return;
100 | }
101 |
102 | [self executeLocked:^() {
103 |
104 | if ([self->_databaseInPool containsObject:db]) {
105 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise];
106 | }
107 |
108 | [self->_databaseInPool addObject:db];
109 | [self->_databaseOutPool removeObject:db];
110 |
111 | }];
112 | }
113 |
114 | - (FMDatabase*)db {
115 |
116 | __block FMDatabase *db;
117 |
118 |
119 | [self executeLocked:^() {
120 | db = [self->_databaseInPool lastObject];
121 |
122 | BOOL shouldNotifyDelegate = NO;
123 |
124 | if (db) {
125 | [self->_databaseOutPool addObject:db];
126 | [self->_databaseInPool removeLastObject];
127 | }
128 | else {
129 |
130 | if (self->_maximumNumberOfDatabasesToCreate) {
131 | NSUInteger currentCount = [self->_databaseOutPool count] + [self->_databaseInPool count];
132 |
133 | if (currentCount >= self->_maximumNumberOfDatabasesToCreate) {
134 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount);
135 | return;
136 | }
137 | }
138 |
139 | db = [[[self class] databaseClass] databaseWithPath:self->_path];
140 | shouldNotifyDelegate = YES;
141 | }
142 |
143 | //This ensures that the db is opened before returning
144 | #if SQLITE_VERSION_NUMBER >= 3005000
145 | BOOL success = [db openWithFlags:self->_openFlags vfs:self->_vfsName];
146 | #else
147 | BOOL success = [db open];
148 | #endif
149 | if (success) {
150 | if ([self->_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![self->_delegate databasePool:self shouldAddDatabaseToPool:db]) {
151 | [db close];
152 | db = 0x00;
153 | }
154 | else {
155 | //It should not get added in the pool twice if lastObject was found
156 | if (![self->_databaseOutPool containsObject:db]) {
157 | [self->_databaseOutPool addObject:db];
158 |
159 | if (shouldNotifyDelegate && [self->_delegate respondsToSelector:@selector(databasePool:didAddDatabase:)]) {
160 | [self->_delegate databasePool:self didAddDatabase:db];
161 | }
162 | }
163 | }
164 | }
165 | else {
166 | NSLog(@"Could not open up the database at path %@", self->_path);
167 | db = 0x00;
168 | }
169 | }];
170 |
171 | return db;
172 | }
173 |
174 | - (NSUInteger)countOfCheckedInDatabases {
175 |
176 | __block NSUInteger count;
177 |
178 | [self executeLocked:^() {
179 | count = [self->_databaseInPool count];
180 | }];
181 |
182 | return count;
183 | }
184 |
185 | - (NSUInteger)countOfCheckedOutDatabases {
186 |
187 | __block NSUInteger count;
188 |
189 | [self executeLocked:^() {
190 | count = [self->_databaseOutPool count];
191 | }];
192 |
193 | return count;
194 | }
195 |
196 | - (NSUInteger)countOfOpenDatabases {
197 | __block NSUInteger count;
198 |
199 | [self executeLocked:^() {
200 | count = [self->_databaseOutPool count] + [self->_databaseInPool count];
201 | }];
202 |
203 | return count;
204 | }
205 |
206 | - (void)releaseAllDatabases {
207 | [self executeLocked:^() {
208 | [self->_databaseOutPool removeAllObjects];
209 | [self->_databaseInPool removeAllObjects];
210 | }];
211 | }
212 |
213 | - (void)inDatabase:(void (^)(FMDatabase *db))block {
214 |
215 | FMDatabase *db = [self db];
216 |
217 | block(db);
218 |
219 | [self pushDatabaseBackInPool:db];
220 | }
221 |
222 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block {
223 |
224 | BOOL shouldRollback = NO;
225 |
226 | FMDatabase *db = [self db];
227 |
228 | if (useDeferred) {
229 | [db beginDeferredTransaction];
230 | }
231 | else {
232 | [db beginTransaction];
233 | }
234 |
235 |
236 | block(db, &shouldRollback);
237 |
238 | if (shouldRollback) {
239 | [db rollback];
240 | }
241 | else {
242 | [db commit];
243 | }
244 |
245 | [self pushDatabaseBackInPool:db];
246 | }
247 |
248 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
249 | [self beginTransaction:YES withBlock:block];
250 | }
251 |
252 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block {
253 | [self beginTransaction:NO withBlock:block];
254 | }
255 |
256 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block {
257 | #if SQLITE_VERSION_NUMBER >= 3007000
258 | static unsigned long savePointIdx = 0;
259 |
260 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++];
261 |
262 | BOOL shouldRollback = NO;
263 |
264 | FMDatabase *db = [self db];
265 |
266 | NSError *err = 0x00;
267 |
268 | if (![db startSavePointWithName:name error:&err]) {
269 | [self pushDatabaseBackInPool:db];
270 | return err;
271 | }
272 |
273 | block(db, &shouldRollback);
274 |
275 | if (shouldRollback) {
276 | // We need to rollback and release this savepoint to remove it
277 | [db rollbackToSavePointWithName:name error:&err];
278 | }
279 | [db releaseSavePointWithName:name error:&err];
280 |
281 | [self pushDatabaseBackInPool:db];
282 |
283 | return err;
284 | #else
285 | NSString *errorMessage = NSLocalizedString(@"Save point functions require SQLite 3.7", nil);
286 | if (self.logsErrors) NSLog(@"%@", errorMessage);
287 | return [NSError errorWithDomain:@"FMDatabase" code:0 userInfo:@{NSLocalizedDescriptionKey : errorMessage}];
288 | #endif
289 | }
290 |
291 | @end
292 |
--------------------------------------------------------------------------------
/ToDoApp/FMResultSet.m:
--------------------------------------------------------------------------------
1 | #import "FMResultSet.h"
2 | #import "FMDatabase.h"
3 | #import "unistd.h"
4 |
5 | #if FMDB_SQLITE_STANDALONE
6 | #import
7 | #else
8 | #import
9 | #endif
10 |
11 | @interface FMDatabase ()
12 | - (void)resultSetDidClose:(FMResultSet *)resultSet;
13 | @end
14 |
15 |
16 | @implementation FMResultSet
17 | @synthesize query=_query;
18 | @synthesize statement=_statement;
19 |
20 | + (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB {
21 |
22 | FMResultSet *rs = [[FMResultSet alloc] init];
23 |
24 | [rs setStatement:statement];
25 | [rs setParentDB:aDB];
26 |
27 | NSParameterAssert(![statement inUse]);
28 | [statement setInUse:YES]; // weak reference
29 |
30 | return FMDBReturnAutoreleased(rs);
31 | }
32 |
33 | #if ! __has_feature(objc_arc)
34 | - (void)finalize {
35 | [self close];
36 | [super finalize];
37 | }
38 | #endif
39 |
40 | - (void)dealloc {
41 | [self close];
42 |
43 | FMDBRelease(_query);
44 | _query = nil;
45 |
46 | FMDBRelease(_columnNameToIndexMap);
47 | _columnNameToIndexMap = nil;
48 |
49 | #if ! __has_feature(objc_arc)
50 | [super dealloc];
51 | #endif
52 | }
53 |
54 | - (void)close {
55 | [_statement reset];
56 | FMDBRelease(_statement);
57 | _statement = nil;
58 |
59 | // we don't need this anymore... (i think)
60 | //[_parentDB setInUse:NO];
61 | [_parentDB resultSetDidClose:self];
62 | _parentDB = nil;
63 | }
64 |
65 | - (int)columnCount {
66 | return sqlite3_column_count([_statement statement]);
67 | }
68 |
69 | - (NSMutableDictionary *)columnNameToIndexMap {
70 | if (!_columnNameToIndexMap) {
71 | int columnCount = sqlite3_column_count([_statement statement]);
72 | _columnNameToIndexMap = [[NSMutableDictionary alloc] initWithCapacity:(NSUInteger)columnCount];
73 | int columnIdx = 0;
74 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
75 | [_columnNameToIndexMap setObject:[NSNumber numberWithInt:columnIdx]
76 | forKey:[[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)] lowercaseString]];
77 | }
78 | }
79 | return _columnNameToIndexMap;
80 | }
81 |
82 | - (void)kvcMagic:(id)object {
83 |
84 | int columnCount = sqlite3_column_count([_statement statement]);
85 |
86 | int columnIdx = 0;
87 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
88 |
89 | const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
90 |
91 | // check for a null row
92 | if (c) {
93 | NSString *s = [NSString stringWithUTF8String:c];
94 |
95 | [object setValue:s forKey:[NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)]];
96 | }
97 | }
98 | }
99 |
100 | #pragma clang diagnostic push
101 | #pragma clang diagnostic ignored "-Wdeprecated-implementations"
102 |
103 | - (NSDictionary*)resultDict {
104 |
105 | NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
106 |
107 | if (num_cols > 0) {
108 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
109 |
110 | NSEnumerator *columnNames = [[self columnNameToIndexMap] keyEnumerator];
111 | NSString *columnName = nil;
112 | while ((columnName = [columnNames nextObject])) {
113 | id objectValue = [self objectForColumnName:columnName];
114 | [dict setObject:objectValue forKey:columnName];
115 | }
116 |
117 | return FMDBReturnAutoreleased([dict copy]);
118 | }
119 | else {
120 | NSLog(@"Warning: There seem to be no columns in this set.");
121 | }
122 |
123 | return nil;
124 | }
125 |
126 | #pragma clang diagnostic pop
127 |
128 | - (NSDictionary*)resultDictionary {
129 |
130 | NSUInteger num_cols = (NSUInteger)sqlite3_data_count([_statement statement]);
131 |
132 | if (num_cols > 0) {
133 | NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:num_cols];
134 |
135 | int columnCount = sqlite3_column_count([_statement statement]);
136 |
137 | int columnIdx = 0;
138 | for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
139 |
140 | NSString *columnName = [NSString stringWithUTF8String:sqlite3_column_name([_statement statement], columnIdx)];
141 | id objectValue = [self objectForColumnIndex:columnIdx];
142 | [dict setObject:objectValue forKey:columnName];
143 | }
144 |
145 | return dict;
146 | }
147 | else {
148 | NSLog(@"Warning: There seem to be no columns in this set.");
149 | }
150 |
151 | return nil;
152 | }
153 |
154 |
155 |
156 |
157 | - (BOOL)next {
158 | return [self nextWithError:nil];
159 | }
160 |
161 | - (BOOL)nextWithError:(NSError **)outErr {
162 |
163 | int rc = sqlite3_step([_statement statement]);
164 |
165 | if (SQLITE_BUSY == rc || SQLITE_LOCKED == rc) {
166 | NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [_parentDB databasePath]);
167 | NSLog(@"Database busy");
168 | if (outErr) {
169 | *outErr = [_parentDB lastError];
170 | }
171 | }
172 | else if (SQLITE_DONE == rc || SQLITE_ROW == rc) {
173 | // all is well, let's return.
174 | }
175 | else if (SQLITE_ERROR == rc) {
176 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
177 | if (outErr) {
178 | *outErr = [_parentDB lastError];
179 | }
180 | }
181 | else if (SQLITE_MISUSE == rc) {
182 | // uh oh.
183 | NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
184 | if (outErr) {
185 | if (_parentDB) {
186 | *outErr = [_parentDB lastError];
187 | }
188 | else {
189 | // If 'next' or 'nextWithError' is called after the result set is closed,
190 | // we need to return the appropriate error.
191 | NSDictionary* errorMessage = [NSDictionary dictionaryWithObject:@"parentDB does not exist" forKey:NSLocalizedDescriptionKey];
192 | *outErr = [NSError errorWithDomain:@"FMDatabase" code:SQLITE_MISUSE userInfo:errorMessage];
193 | }
194 |
195 | }
196 | }
197 | else {
198 | // wtf?
199 | NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([_parentDB sqliteHandle]));
200 | if (outErr) {
201 | *outErr = [_parentDB lastError];
202 | }
203 | }
204 |
205 |
206 | if (rc != SQLITE_ROW) {
207 | [self close];
208 | }
209 |
210 | return (rc == SQLITE_ROW);
211 | }
212 |
213 | - (BOOL)hasAnotherRow {
214 | return sqlite3_errcode([_parentDB sqliteHandle]) == SQLITE_ROW;
215 | }
216 |
217 | - (int)columnIndexForName:(NSString*)columnName {
218 | columnName = [columnName lowercaseString];
219 |
220 | NSNumber *n = [[self columnNameToIndexMap] objectForKey:columnName];
221 |
222 | if (n) {
223 | return [n intValue];
224 | }
225 |
226 | NSLog(@"Warning: I could not find the column named '%@'.", columnName);
227 |
228 | return -1;
229 | }
230 |
231 |
232 |
233 | - (int)intForColumn:(NSString*)columnName {
234 | return [self intForColumnIndex:[self columnIndexForName:columnName]];
235 | }
236 |
237 | - (int)intForColumnIndex:(int)columnIdx {
238 | return sqlite3_column_int([_statement statement], columnIdx);
239 | }
240 |
241 | - (long)longForColumn:(NSString*)columnName {
242 | return [self longForColumnIndex:[self columnIndexForName:columnName]];
243 | }
244 |
245 | - (long)longForColumnIndex:(int)columnIdx {
246 | return (long)sqlite3_column_int64([_statement statement], columnIdx);
247 | }
248 |
249 | - (long long int)longLongIntForColumn:(NSString*)columnName {
250 | return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
251 | }
252 |
253 | - (long long int)longLongIntForColumnIndex:(int)columnIdx {
254 | return sqlite3_column_int64([_statement statement], columnIdx);
255 | }
256 |
257 | - (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName {
258 | return [self unsignedLongLongIntForColumnIndex:[self columnIndexForName:columnName]];
259 | }
260 |
261 | - (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx {
262 | return (unsigned long long int)[self longLongIntForColumnIndex:columnIdx];
263 | }
264 |
265 | - (BOOL)boolForColumn:(NSString*)columnName {
266 | return [self boolForColumnIndex:[self columnIndexForName:columnName]];
267 | }
268 |
269 | - (BOOL)boolForColumnIndex:(int)columnIdx {
270 | return ([self intForColumnIndex:columnIdx] != 0);
271 | }
272 |
273 | - (double)doubleForColumn:(NSString*)columnName {
274 | return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
275 | }
276 |
277 | - (double)doubleForColumnIndex:(int)columnIdx {
278 | return sqlite3_column_double([_statement statement], columnIdx);
279 | }
280 |
281 | - (NSString*)stringForColumnIndex:(int)columnIdx {
282 |
283 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
284 | return nil;
285 | }
286 |
287 | const char *c = (const char *)sqlite3_column_text([_statement statement], columnIdx);
288 |
289 | if (!c) {
290 | // null row.
291 | return nil;
292 | }
293 |
294 | return [NSString stringWithUTF8String:c];
295 | }
296 |
297 | - (NSString*)stringForColumn:(NSString*)columnName {
298 | return [self stringForColumnIndex:[self columnIndexForName:columnName]];
299 | }
300 |
301 | - (NSDate*)dateForColumn:(NSString*)columnName {
302 | return [self dateForColumnIndex:[self columnIndexForName:columnName]];
303 | }
304 |
305 | - (NSDate*)dateForColumnIndex:(int)columnIdx {
306 |
307 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
308 | return nil;
309 | }
310 |
311 | return [_parentDB hasDateFormatter] ? [_parentDB dateFromString:[self stringForColumnIndex:columnIdx]] : [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
312 | }
313 |
314 |
315 | - (NSData*)dataForColumn:(NSString*)columnName {
316 | return [self dataForColumnIndex:[self columnIndexForName:columnName]];
317 | }
318 |
319 | - (NSData*)dataForColumnIndex:(int)columnIdx {
320 |
321 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
322 | return nil;
323 | }
324 |
325 | const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx);
326 | int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
327 |
328 | if (dataBuffer == NULL) {
329 | return nil;
330 | }
331 |
332 | return [NSData dataWithBytes:(const void *)dataBuffer length:(NSUInteger)dataSize];
333 | }
334 |
335 |
336 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName {
337 | return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
338 | }
339 |
340 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx {
341 |
342 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
343 | return nil;
344 | }
345 |
346 | const char *dataBuffer = sqlite3_column_blob([_statement statement], columnIdx);
347 | int dataSize = sqlite3_column_bytes([_statement statement], columnIdx);
348 |
349 | NSData *data = [NSData dataWithBytesNoCopy:(void *)dataBuffer length:(NSUInteger)dataSize freeWhenDone:NO];
350 |
351 | return data;
352 | }
353 |
354 |
355 | - (BOOL)columnIndexIsNull:(int)columnIdx {
356 | return sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL;
357 | }
358 |
359 | - (BOOL)columnIsNull:(NSString*)columnName {
360 | return [self columnIndexIsNull:[self columnIndexForName:columnName]];
361 | }
362 |
363 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx {
364 |
365 | if (sqlite3_column_type([_statement statement], columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
366 | return nil;
367 | }
368 |
369 | return sqlite3_column_text([_statement statement], columnIdx);
370 | }
371 |
372 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName {
373 | return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
374 | }
375 |
376 | - (id)objectForColumnIndex:(int)columnIdx {
377 | int columnType = sqlite3_column_type([_statement statement], columnIdx);
378 |
379 | id returnValue = nil;
380 |
381 | if (columnType == SQLITE_INTEGER) {
382 | returnValue = [NSNumber numberWithLongLong:[self longLongIntForColumnIndex:columnIdx]];
383 | }
384 | else if (columnType == SQLITE_FLOAT) {
385 | returnValue = [NSNumber numberWithDouble:[self doubleForColumnIndex:columnIdx]];
386 | }
387 | else if (columnType == SQLITE_BLOB) {
388 | returnValue = [self dataForColumnIndex:columnIdx];
389 | }
390 | else {
391 | //default to a string for everything else
392 | returnValue = [self stringForColumnIndex:columnIdx];
393 | }
394 |
395 | if (returnValue == nil) {
396 | returnValue = [NSNull null];
397 | }
398 |
399 | return returnValue;
400 | }
401 |
402 | - (id)objectForColumnName:(NSString*)columnName {
403 | return [self objectForColumnIndex:[self columnIndexForName:columnName]];
404 | }
405 |
406 | // returns autoreleased NSString containing the name of the column in the result set
407 | - (NSString*)columnNameForIndex:(int)columnIdx {
408 | return [NSString stringWithUTF8String: sqlite3_column_name([_statement statement], columnIdx)];
409 | }
410 |
411 | - (void)setParentDB:(FMDatabase *)newDb {
412 | _parentDB = newDb;
413 | }
414 |
415 | - (id)objectAtIndexedSubscript:(int)columnIdx {
416 | return [self objectForColumnIndex:columnIdx];
417 | }
418 |
419 | - (id)objectForKeyedSubscript:(NSString *)columnName {
420 | return [self objectForColumnName:columnName];
421 | }
422 |
423 |
424 | @end
425 |
--------------------------------------------------------------------------------
/ToDoApp/FMResultSet.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #ifndef __has_feature // Optional.
4 | #define __has_feature(x) 0 // Compatibility with non-clang compilers.
5 | #endif
6 |
7 | #ifndef NS_RETURNS_NOT_RETAINED
8 | #if __has_feature(attribute_ns_returns_not_retained)
9 | #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
10 | #else
11 | #define NS_RETURNS_NOT_RETAINED
12 | #endif
13 | #endif
14 |
15 | @class FMDatabase;
16 | @class FMStatement;
17 |
18 | /** Represents the results of executing a query on an ``.
19 |
20 | ### See also
21 |
22 | - ``
23 | */
24 |
25 | @interface FMResultSet : NSObject {
26 | FMDatabase *_parentDB;
27 | FMStatement *_statement;
28 |
29 | NSString *_query;
30 | NSMutableDictionary *_columnNameToIndexMap;
31 | }
32 |
33 | ///-----------------
34 | /// @name Properties
35 | ///-----------------
36 |
37 | /** Executed query */
38 |
39 | @property (atomic, retain) NSString *query;
40 |
41 | /** `NSMutableDictionary` mapping column names to numeric index */
42 |
43 | @property (readonly) NSMutableDictionary *columnNameToIndexMap;
44 |
45 | /** `FMStatement` used by result set. */
46 |
47 | @property (atomic, retain) FMStatement *statement;
48 |
49 | ///------------------------------------
50 | /// @name Creating and closing database
51 | ///------------------------------------
52 |
53 | /** Create result set from ``
54 |
55 | @param statement A `` to be performed
56 |
57 | @param aDB A `` to be used
58 |
59 | @return A `FMResultSet` on success; `nil` on failure
60 | */
61 |
62 | + (instancetype)resultSetWithStatement:(FMStatement *)statement usingParentDatabase:(FMDatabase*)aDB;
63 |
64 | /** Close result set */
65 |
66 | - (void)close;
67 |
68 | - (void)setParentDB:(FMDatabase *)newDb;
69 |
70 | ///---------------------------------------
71 | /// @name Iterating through the result set
72 | ///---------------------------------------
73 |
74 | /** Retrieve next row for result set.
75 |
76 | You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
77 |
78 | @return `YES` if row successfully retrieved; `NO` if end of result set reached
79 |
80 | @see hasAnotherRow
81 | */
82 |
83 | - (BOOL)next;
84 |
85 | /** Retrieve next row for result set.
86 |
87 | You must always invoke `next` or `nextWithError` before attempting to access the values returned in a query, even if you're only expecting one.
88 |
89 | @param outErr A 'NSError' object to receive any error object (if any).
90 |
91 | @return 'YES' if row successfully retrieved; 'NO' if end of result set reached
92 |
93 | @see hasAnotherRow
94 | */
95 |
96 | - (BOOL)nextWithError:(NSError **)outErr;
97 |
98 | /** Did the last call to `` succeed in retrieving another row?
99 |
100 | @return `YES` if the last call to `` succeeded in retrieving another record; `NO` if not.
101 |
102 | @see next
103 |
104 | @warning The `hasAnotherRow` method must follow a call to ``. If the previous database interaction was something other than a call to `next`, then this method may return `NO`, whether there is another row of data or not.
105 | */
106 |
107 | - (BOOL)hasAnotherRow;
108 |
109 | ///---------------------------------------------
110 | /// @name Retrieving information from result set
111 | ///---------------------------------------------
112 |
113 | /** How many columns in result set
114 |
115 | @return Integer value of the number of columns.
116 | */
117 |
118 | - (int)columnCount;
119 |
120 | /** Column index for column name
121 |
122 | @param columnName `NSString` value of the name of the column.
123 |
124 | @return Zero-based index for column.
125 | */
126 |
127 | - (int)columnIndexForName:(NSString*)columnName;
128 |
129 | /** Column name for column index
130 |
131 | @param columnIdx Zero-based index for column.
132 |
133 | @return columnName `NSString` value of the name of the column.
134 | */
135 |
136 | - (NSString*)columnNameForIndex:(int)columnIdx;
137 |
138 | /** Result set integer value for column.
139 |
140 | @param columnName `NSString` value of the name of the column.
141 |
142 | @return `int` value of the result set's column.
143 | */
144 |
145 | - (int)intForColumn:(NSString*)columnName;
146 |
147 | /** Result set integer value for column.
148 |
149 | @param columnIdx Zero-based index for column.
150 |
151 | @return `int` value of the result set's column.
152 | */
153 |
154 | - (int)intForColumnIndex:(int)columnIdx;
155 |
156 | /** Result set `long` value for column.
157 |
158 | @param columnName `NSString` value of the name of the column.
159 |
160 | @return `long` value of the result set's column.
161 | */
162 |
163 | - (long)longForColumn:(NSString*)columnName;
164 |
165 | /** Result set long value for column.
166 |
167 | @param columnIdx Zero-based index for column.
168 |
169 | @return `long` value of the result set's column.
170 | */
171 |
172 | - (long)longForColumnIndex:(int)columnIdx;
173 |
174 | /** Result set `long long int` value for column.
175 |
176 | @param columnName `NSString` value of the name of the column.
177 |
178 | @return `long long int` value of the result set's column.
179 | */
180 |
181 | - (long long int)longLongIntForColumn:(NSString*)columnName;
182 |
183 | /** Result set `long long int` value for column.
184 |
185 | @param columnIdx Zero-based index for column.
186 |
187 | @return `long long int` value of the result set's column.
188 | */
189 |
190 | - (long long int)longLongIntForColumnIndex:(int)columnIdx;
191 |
192 | /** Result set `unsigned long long int` value for column.
193 |
194 | @param columnName `NSString` value of the name of the column.
195 |
196 | @return `unsigned long long int` value of the result set's column.
197 | */
198 |
199 | - (unsigned long long int)unsignedLongLongIntForColumn:(NSString*)columnName;
200 |
201 | /** Result set `unsigned long long int` value for column.
202 |
203 | @param columnIdx Zero-based index for column.
204 |
205 | @return `unsigned long long int` value of the result set's column.
206 | */
207 |
208 | - (unsigned long long int)unsignedLongLongIntForColumnIndex:(int)columnIdx;
209 |
210 | /** Result set `BOOL` value for column.
211 |
212 | @param columnName `NSString` value of the name of the column.
213 |
214 | @return `BOOL` value of the result set's column.
215 | */
216 |
217 | - (BOOL)boolForColumn:(NSString*)columnName;
218 |
219 | /** Result set `BOOL` value for column.
220 |
221 | @param columnIdx Zero-based index for column.
222 |
223 | @return `BOOL` value of the result set's column.
224 | */
225 |
226 | - (BOOL)boolForColumnIndex:(int)columnIdx;
227 |
228 | /** Result set `double` value for column.
229 |
230 | @param columnName `NSString` value of the name of the column.
231 |
232 | @return `double` value of the result set's column.
233 |
234 | */
235 |
236 | - (double)doubleForColumn:(NSString*)columnName;
237 |
238 | /** Result set `double` value for column.
239 |
240 | @param columnIdx Zero-based index for column.
241 |
242 | @return `double` value of the result set's column.
243 |
244 | */
245 |
246 | - (double)doubleForColumnIndex:(int)columnIdx;
247 |
248 | /** Result set `NSString` value for column.
249 |
250 | @param columnName `NSString` value of the name of the column.
251 |
252 | @return `NSString` value of the result set's column.
253 |
254 | */
255 |
256 | - (NSString*)stringForColumn:(NSString*)columnName;
257 |
258 | /** Result set `NSString` value for column.
259 |
260 | @param columnIdx Zero-based index for column.
261 |
262 | @return `NSString` value of the result set's column.
263 | */
264 |
265 | - (NSString*)stringForColumnIndex:(int)columnIdx;
266 |
267 | /** Result set `NSDate` value for column.
268 |
269 | @param columnName `NSString` value of the name of the column.
270 |
271 | @return `NSDate` value of the result set's column.
272 | */
273 |
274 | - (NSDate*)dateForColumn:(NSString*)columnName;
275 |
276 | /** Result set `NSDate` value for column.
277 |
278 | @param columnIdx Zero-based index for column.
279 |
280 | @return `NSDate` value of the result set's column.
281 |
282 | */
283 |
284 | - (NSDate*)dateForColumnIndex:(int)columnIdx;
285 |
286 | /** Result set `NSData` value for column.
287 |
288 | This is useful when storing binary data in table (such as image or the like).
289 |
290 | @param columnName `NSString` value of the name of the column.
291 |
292 | @return `NSData` value of the result set's column.
293 |
294 | */
295 |
296 | - (NSData*)dataForColumn:(NSString*)columnName;
297 |
298 | /** Result set `NSData` value for column.
299 |
300 | @param columnIdx Zero-based index for column.
301 |
302 | @return `NSData` value of the result set's column.
303 | */
304 |
305 | - (NSData*)dataForColumnIndex:(int)columnIdx;
306 |
307 | /** Result set `(const unsigned char *)` value for column.
308 |
309 | @param columnName `NSString` value of the name of the column.
310 |
311 | @return `(const unsigned char *)` value of the result set's column.
312 | */
313 |
314 | - (const unsigned char *)UTF8StringForColumnName:(NSString*)columnName;
315 |
316 | /** Result set `(const unsigned char *)` value for column.
317 |
318 | @param columnIdx Zero-based index for column.
319 |
320 | @return `(const unsigned char *)` value of the result set's column.
321 | */
322 |
323 | - (const unsigned char *)UTF8StringForColumnIndex:(int)columnIdx;
324 |
325 | /** Result set object for column.
326 |
327 | @param columnName `NSString` value of the name of the column.
328 |
329 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
330 |
331 | @see objectForKeyedSubscript:
332 | */
333 |
334 | - (id)objectForColumnName:(NSString*)columnName;
335 |
336 | /** Result set object for column.
337 |
338 | @param columnIdx Zero-based index for column.
339 |
340 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
341 |
342 | @see objectAtIndexedSubscript:
343 | */
344 |
345 | - (id)objectForColumnIndex:(int)columnIdx;
346 |
347 | /** Result set object for column.
348 |
349 | This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported:
350 |
351 | id result = rs[@"employee_name"];
352 |
353 | This simplified syntax is equivalent to calling:
354 |
355 | id result = [rs objectForKeyedSubscript:@"employee_name"];
356 |
357 | which is, it turns out, equivalent to calling:
358 |
359 | id result = [rs objectForColumnName:@"employee_name"];
360 |
361 | @param columnName `NSString` value of the name of the column.
362 |
363 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
364 | */
365 |
366 | - (id)objectForKeyedSubscript:(NSString *)columnName;
367 |
368 | /** Result set object for column.
369 |
370 | This method allows the use of the "boxed" syntax supported in Modern Objective-C. For example, by defining this method, the following syntax is now supported:
371 |
372 | id result = rs[0];
373 |
374 | This simplified syntax is equivalent to calling:
375 |
376 | id result = [rs objectForKeyedSubscript:0];
377 |
378 | which is, it turns out, equivalent to calling:
379 |
380 | id result = [rs objectForColumnName:0];
381 |
382 | @param columnIdx Zero-based index for column.
383 |
384 | @return Either `NSNumber`, `NSString`, `NSData`, or `NSNull`. If the column was `NULL`, this returns `[NSNull null]` object.
385 | */
386 |
387 | - (id)objectAtIndexedSubscript:(int)columnIdx;
388 |
389 | /** Result set `NSData` value for column.
390 |
391 | @param columnName `NSString` value of the name of the column.
392 |
393 | @return `NSData` value of the result set's column.
394 |
395 | @warning If you are going to use this data after you iterate over the next row, or after you close the
396 | result set, make sure to make a copy of the data first (or just use ``/``)
397 | If you don't, you're going to be in a world of hurt when you try and use the data.
398 |
399 | */
400 |
401 | - (NSData*)dataNoCopyForColumn:(NSString*)columnName NS_RETURNS_NOT_RETAINED;
402 |
403 | /** Result set `NSData` value for column.
404 |
405 | @param columnIdx Zero-based index for column.
406 |
407 | @return `NSData` value of the result set's column.
408 |
409 | @warning If you are going to use this data after you iterate over the next row, or after you close the
410 | result set, make sure to make a copy of the data first (or just use ``/``)
411 | If you don't, you're going to be in a world of hurt when you try and use the data.
412 |
413 | */
414 |
415 | - (NSData*)dataNoCopyForColumnIndex:(int)columnIdx NS_RETURNS_NOT_RETAINED;
416 |
417 | /** Is the column `NULL`?
418 |
419 | @param columnIdx Zero-based index for column.
420 |
421 | @return `YES` if column is `NULL`; `NO` if not `NULL`.
422 | */
423 |
424 | - (BOOL)columnIndexIsNull:(int)columnIdx;
425 |
426 | /** Is the column `NULL`?
427 |
428 | @param columnName `NSString` value of the name of the column.
429 |
430 | @return `YES` if column is `NULL`; `NO` if not `NULL`.
431 | */
432 |
433 | - (BOOL)columnIsNull:(NSString*)columnName;
434 |
435 |
436 | /** Returns a dictionary of the row results mapped to case sensitive keys of the column names.
437 |
438 | @returns `NSDictionary` of the row results.
439 |
440 | @warning The keys to the dictionary are case sensitive of the column names.
441 | */
442 |
443 | - (NSDictionary*)resultDictionary;
444 |
445 | /** Returns a dictionary of the row results
446 |
447 | @see resultDictionary
448 |
449 | @warning **Deprecated**: Please use `` instead. Also, beware that `` is case sensitive!
450 | */
451 |
452 | - (NSDictionary*)resultDict __attribute__ ((deprecated));
453 |
454 | ///-----------------------------
455 | /// @name Key value coding magic
456 | ///-----------------------------
457 |
458 | /** Performs `setValue` to yield support for key value observing.
459 |
460 | @param object The object for which the values will be set. This is the key-value-coding compliant object that you might, for example, observe.
461 |
462 | */
463 |
464 | - (void)kvcMagic:(id)object;
465 |
466 |
467 | @end
468 |
469 |
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/xcuserdata/bilgecakar.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
21 |
22 |
23 |
25 |
37 |
38 |
39 |
41 |
53 |
54 |
55 |
57 |
69 |
70 |
71 |
73 |
85 |
86 |
87 |
89 |
101 |
102 |
103 |
105 |
117 |
118 |
119 |
121 |
133 |
134 |
135 |
137 |
149 |
150 |
151 |
153 |
165 |
166 |
167 |
169 |
181 |
182 |
183 |
185 |
197 |
198 |
199 |
201 |
213 |
214 |
215 |
217 |
229 |
230 |
231 |
233 |
245 |
246 |
247 |
249 |
261 |
262 |
263 |
265 |
277 |
278 |
279 |
281 |
293 |
294 |
295 |
297 |
309 |
310 |
311 |
313 |
325 |
326 |
327 |
328 |
329 |
--------------------------------------------------------------------------------
/ToDoApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 19803F7D27E5E8A7001930A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F7C27E5E8A7001930A4 /* AppDelegate.swift */; };
11 | 19803F7F27E5E8A7001930A4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F7E27E5E8A7001930A4 /* SceneDelegate.swift */; };
12 | 19803F8127E5E8A7001930A4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F8027E5E8A7001930A4 /* ViewController.swift */; };
13 | 19803F8427E5E8A7001930A4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19803F8227E5E8A7001930A4 /* Main.storyboard */; };
14 | 19803F8627E5E8AB001930A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19803F8527E5E8AB001930A4 /* Assets.xcassets */; };
15 | 19803F8927E5E8AB001930A4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19803F8727E5E8AB001930A4 /* LaunchScreen.storyboard */; };
16 | 19803F9427E5E8AB001930A4 /* ToDoAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F9327E5E8AB001930A4 /* ToDoAppTests.swift */; };
17 | 19803F9E27E5E8AB001930A4 /* ToDoAppUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F9D27E5E8AB001930A4 /* ToDoAppUITests.swift */; };
18 | 19803FA027E5E8AB001930A4 /* ToDoAppUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803F9F27E5E8AB001930A4 /* ToDoAppUITestsLaunchTests.swift */; };
19 | 19803FB927E5EBEA001930A4 /* Roboto-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FAD27E5EBE8001930A4 /* Roboto-BoldItalic.ttf */; };
20 | 19803FBA27E5EBEA001930A4 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FAE27E5EBE9001930A4 /* Roboto-BlackItalic.ttf */; };
21 | 19803FBB27E5EBEA001930A4 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FAF27E5EBE9001930A4 /* Roboto-Bold.ttf */; };
22 | 19803FBC27E5EBEA001930A4 /* Roboto-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB027E5EBE9001930A4 /* Roboto-Italic.ttf */; };
23 | 19803FBD27E5EBEA001930A4 /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB127E5EBE9001930A4 /* Roboto-LightItalic.ttf */; };
24 | 19803FBE27E5EBEA001930A4 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB227E5EBE9001930A4 /* Roboto-Medium.ttf */; };
25 | 19803FBF27E5EBEA001930A4 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB327E5EBE9001930A4 /* Roboto-Regular.ttf */; };
26 | 19803FC027E5EBEA001930A4 /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB427E5EBE9001930A4 /* Roboto-Thin.ttf */; };
27 | 19803FC127E5EBEA001930A4 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB527E5EBEA001930A4 /* Roboto-Black.ttf */; };
28 | 19803FC227E5EBEA001930A4 /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB627E5EBEA001930A4 /* Roboto-Light.ttf */; };
29 | 19803FC327E5EBEA001930A4 /* Roboto-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB727E5EBEA001930A4 /* Roboto-MediumItalic.ttf */; };
30 | 19803FC427E5EBEA001930A4 /* Roboto-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 19803FB827E5EBEA001930A4 /* Roboto-ThinItalic.ttf */; };
31 | 19803FC627E603FE001930A4 /* AddTaskViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19803FC527E603FE001930A4 /* AddTaskViewController.swift */; };
32 | 199C549B27E8346000B80DB2 /* FMDatabasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = 199C549327E8345F00B80DB2 /* FMDatabasePool.m */; };
33 | 199C549C27E8346000B80DB2 /* FMResultSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 199C549627E8346000B80DB2 /* FMResultSet.m */; };
34 | 199C549D27E8346000B80DB2 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 199C549727E8346000B80DB2 /* FMDatabase.m */; };
35 | 199C549E27E8346000B80DB2 /* FMDatabaseQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 199C549927E8346000B80DB2 /* FMDatabaseQueue.m */; };
36 | 199C549F27E8346000B80DB2 /* FMDatabaseAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 199C549A27E8346000B80DB2 /* FMDatabaseAdditions.m */; };
37 | 199C54AC27E8730900B80DB2 /* gorevler.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 199C54AB27E8730900B80DB2 /* gorevler.sqlite */; };
38 | 19DF7E4F27E7C7970012C4E9 /* TaskTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E4E27E7C7970012C4E9 /* TaskTableViewCell.swift */; };
39 | 19DF7E5127E7CB230012C4E9 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E5027E7CB230012C4E9 /* Task.swift */; };
40 | 19DF7E6227E7DFED0012C4E9 /* HomePageProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E6127E7DFED0012C4E9 /* HomePageProtocols.swift */; };
41 | 19DF7E6427E7E5A80012C4E9 /* HomeInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E6327E7E5A80012C4E9 /* HomeInteractor.swift */; };
42 | 19DF7E6627E7E7EA0012C4E9 /* HomePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E6527E7E7EA0012C4E9 /* HomePresenter.swift */; };
43 | 19DF7E6827E7E91C0012C4E9 /* HomeRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E6727E7E91C0012C4E9 /* HomeRouter.swift */; };
44 | 19DF7E6A27E7ED740012C4E9 /* TaskDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E6927E7ED740012C4E9 /* TaskDetailViewController.swift */; };
45 | 19DF7E7227E7EE050012C4E9 /* TaskAddProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7127E7EE050012C4E9 /* TaskAddProtocols.swift */; };
46 | 19DF7E7427E7EF960012C4E9 /* TaskAddInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7327E7EF960012C4E9 /* TaskAddInteractor.swift */; };
47 | 19DF7E7627E7F05E0012C4E9 /* TaskAddPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7527E7F05E0012C4E9 /* TaskAddPresenter.swift */; };
48 | 19DF7E7827E7F0B10012C4E9 /* TasAddRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7727E7F0B10012C4E9 /* TasAddRouter.swift */; };
49 | 19DF7E7A27E80D9A0012C4E9 /* TaskDetailProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7927E80D9A0012C4E9 /* TaskDetailProtocols.swift */; };
50 | 19DF7E7C27E80FC00012C4E9 /* TaskDetailInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7B27E80FC00012C4E9 /* TaskDetailInteractor.swift */; };
51 | 19DF7E7E27E810540012C4E9 /* TaskDetailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7D27E810540012C4E9 /* TaskDetailPresenter.swift */; };
52 | 19DF7E8027E810B10012C4E9 /* TaskDetailRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19DF7E7F27E810B10012C4E9 /* TaskDetailRouter.swift */; };
53 | /* End PBXBuildFile section */
54 |
55 | /* Begin PBXContainerItemProxy section */
56 | 19803F9027E5E8AB001930A4 /* PBXContainerItemProxy */ = {
57 | isa = PBXContainerItemProxy;
58 | containerPortal = 19803F7127E5E8A7001930A4 /* Project object */;
59 | proxyType = 1;
60 | remoteGlobalIDString = 19803F7827E5E8A7001930A4;
61 | remoteInfo = ToDoApp;
62 | };
63 | 19803F9A27E5E8AB001930A4 /* PBXContainerItemProxy */ = {
64 | isa = PBXContainerItemProxy;
65 | containerPortal = 19803F7127E5E8A7001930A4 /* Project object */;
66 | proxyType = 1;
67 | remoteGlobalIDString = 19803F7827E5E8A7001930A4;
68 | remoteInfo = ToDoApp;
69 | };
70 | /* End PBXContainerItemProxy section */
71 |
72 | /* Begin PBXFileReference section */
73 | 19803F7927E5E8A7001930A4 /* ToDoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ToDoApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
74 | 19803F7C27E5E8A7001930A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
75 | 19803F7E27E5E8A7001930A4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
76 | 19803F8027E5E8A7001930A4 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
77 | 19803F8327E5E8A7001930A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
78 | 19803F8527E5E8AB001930A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
79 | 19803F8827E5E8AB001930A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
80 | 19803F8A27E5E8AB001930A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
81 | 19803F8F27E5E8AB001930A4 /* ToDoAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ToDoAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
82 | 19803F9327E5E8AB001930A4 /* ToDoAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToDoAppTests.swift; sourceTree = ""; };
83 | 19803F9927E5E8AB001930A4 /* ToDoAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ToDoAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
84 | 19803F9D27E5E8AB001930A4 /* ToDoAppUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToDoAppUITests.swift; sourceTree = ""; };
85 | 19803F9F27E5E8AB001930A4 /* ToDoAppUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToDoAppUITestsLaunchTests.swift; sourceTree = ""; };
86 | 19803FAD27E5EBE8001930A4 /* Roboto-BoldItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-BoldItalic.ttf"; sourceTree = ""; };
87 | 19803FAE27E5EBE9001930A4 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-BlackItalic.ttf"; sourceTree = ""; };
88 | 19803FAF27E5EBE9001930A4 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = ""; };
89 | 19803FB027E5EBE9001930A4 /* Roboto-Italic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Italic.ttf"; sourceTree = ""; };
90 | 19803FB127E5EBE9001930A4 /* Roboto-LightItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-LightItalic.ttf"; sourceTree = ""; };
91 | 19803FB227E5EBE9001930A4 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = ""; };
92 | 19803FB327E5EBE9001930A4 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = ""; };
93 | 19803FB427E5EBE9001930A4 /* Roboto-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Thin.ttf"; sourceTree = ""; };
94 | 19803FB527E5EBEA001930A4 /* Roboto-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Black.ttf"; sourceTree = ""; };
95 | 19803FB627E5EBEA001930A4 /* Roboto-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Light.ttf"; sourceTree = ""; };
96 | 19803FB727E5EBEA001930A4 /* Roboto-MediumItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-MediumItalic.ttf"; sourceTree = ""; };
97 | 19803FB827E5EBEA001930A4 /* Roboto-ThinItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-ThinItalic.ttf"; sourceTree = ""; };
98 | 19803FC527E603FE001930A4 /* AddTaskViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTaskViewController.swift; sourceTree = ""; };
99 | 199C548F27E8345E00B80DB2 /* ToDoApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ToDoApp-Bridging-Header.h"; sourceTree = ""; };
100 | 199C549027E8345F00B80DB2 /* FMDatabasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabasePool.h; sourceTree = ""; };
101 | 199C549127E8345F00B80DB2 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = ""; };
102 | 199C549227E8345F00B80DB2 /* FMResultSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMResultSet.h; sourceTree = ""; };
103 | 199C549327E8345F00B80DB2 /* FMDatabasePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabasePool.m; sourceTree = ""; };
104 | 199C549427E8345F00B80DB2 /* FMDatabaseQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseQueue.h; sourceTree = ""; };
105 | 199C549527E8346000B80DB2 /* FMDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDB.h; sourceTree = ""; };
106 | 199C549627E8346000B80DB2 /* FMResultSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMResultSet.m; sourceTree = ""; };
107 | 199C549727E8346000B80DB2 /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = ""; };
108 | 199C549827E8346000B80DB2 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = ""; };
109 | 199C549927E8346000B80DB2 /* FMDatabaseQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseQueue.m; sourceTree = ""; };
110 | 199C549A27E8346000B80DB2 /* FMDatabaseAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabaseAdditions.m; sourceTree = ""; };
111 | 199C54AA27E870A800B80DB2 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
112 | 199C54AB27E8730900B80DB2 /* gorevler.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = gorevler.sqlite; sourceTree = ""; };
113 | 19DF7E4E27E7C7970012C4E9 /* TaskTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskTableViewCell.swift; sourceTree = ""; };
114 | 19DF7E5027E7CB230012C4E9 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; };
115 | 19DF7E6127E7DFED0012C4E9 /* HomePageProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomePageProtocols.swift; sourceTree = ""; };
116 | 19DF7E6327E7E5A80012C4E9 /* HomeInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeInteractor.swift; sourceTree = ""; };
117 | 19DF7E6527E7E7EA0012C4E9 /* HomePresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomePresenter.swift; sourceTree = ""; };
118 | 19DF7E6727E7E91C0012C4E9 /* HomeRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRouter.swift; sourceTree = ""; };
119 | 19DF7E6927E7ED740012C4E9 /* TaskDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailViewController.swift; sourceTree = ""; };
120 | 19DF7E7127E7EE050012C4E9 /* TaskAddProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskAddProtocols.swift; sourceTree = ""; };
121 | 19DF7E7327E7EF960012C4E9 /* TaskAddInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskAddInteractor.swift; sourceTree = ""; };
122 | 19DF7E7527E7F05E0012C4E9 /* TaskAddPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskAddPresenter.swift; sourceTree = ""; };
123 | 19DF7E7727E7F0B10012C4E9 /* TasAddRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasAddRouter.swift; sourceTree = ""; };
124 | 19DF7E7927E80D9A0012C4E9 /* TaskDetailProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailProtocols.swift; sourceTree = ""; };
125 | 19DF7E7B27E80FC00012C4E9 /* TaskDetailInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailInteractor.swift; sourceTree = ""; };
126 | 19DF7E7D27E810540012C4E9 /* TaskDetailPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailPresenter.swift; sourceTree = ""; };
127 | 19DF7E7F27E810B10012C4E9 /* TaskDetailRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskDetailRouter.swift; sourceTree = ""; };
128 | /* End PBXFileReference section */
129 |
130 | /* Begin PBXFrameworksBuildPhase section */
131 | 19803F7627E5E8A7001930A4 /* Frameworks */ = {
132 | isa = PBXFrameworksBuildPhase;
133 | buildActionMask = 2147483647;
134 | files = (
135 | );
136 | runOnlyForDeploymentPostprocessing = 0;
137 | };
138 | 19803F8C27E5E8AB001930A4 /* Frameworks */ = {
139 | isa = PBXFrameworksBuildPhase;
140 | buildActionMask = 2147483647;
141 | files = (
142 | );
143 | runOnlyForDeploymentPostprocessing = 0;
144 | };
145 | 19803F9627E5E8AB001930A4 /* Frameworks */ = {
146 | isa = PBXFrameworksBuildPhase;
147 | buildActionMask = 2147483647;
148 | files = (
149 | );
150 | runOnlyForDeploymentPostprocessing = 0;
151 | };
152 | /* End PBXFrameworksBuildPhase section */
153 |
154 | /* Begin PBXGroup section */
155 | 19803F7027E5E8A7001930A4 = {
156 | isa = PBXGroup;
157 | children = (
158 | 19803F7B27E5E8A7001930A4 /* ToDoApp */,
159 | 19803F9227E5E8AB001930A4 /* ToDoAppTests */,
160 | 19803F9C27E5E8AB001930A4 /* ToDoAppUITests */,
161 | 19803F7A27E5E8A7001930A4 /* Products */,
162 | 199C54A227E8355300B80DB2 /* Frameworks */,
163 | );
164 | sourceTree = "";
165 | };
166 | 19803F7A27E5E8A7001930A4 /* Products */ = {
167 | isa = PBXGroup;
168 | children = (
169 | 19803F7927E5E8A7001930A4 /* ToDoApp.app */,
170 | 19803F8F27E5E8AB001930A4 /* ToDoAppTests.xctest */,
171 | 19803F9927E5E8AB001930A4 /* ToDoAppUITests.xctest */,
172 | );
173 | name = Products;
174 | sourceTree = "";
175 | };
176 | 19803F7B27E5E8A7001930A4 /* ToDoApp */ = {
177 | isa = PBXGroup;
178 | children = (
179 | 19DF7E5327E7CD310012C4E9 /* homepage-module */,
180 | 19DF7E5A27E7CE130012C4E9 /* taskadd-module */,
181 | 19DF7E5B27E7CE6C0012C4E9 /* taskdetail-module */,
182 | 19DF7E5227E7CCD60012C4E9 /* entity */,
183 | 19803FAC27E5EBC5001930A4 /* Font */,
184 | 19803F7C27E5E8A7001930A4 /* AppDelegate.swift */,
185 | 19803F7E27E5E8A7001930A4 /* SceneDelegate.swift */,
186 | 19803F8227E5E8A7001930A4 /* Main.storyboard */,
187 | 19803F8527E5E8AB001930A4 /* Assets.xcassets */,
188 | 19803F8727E5E8AB001930A4 /* LaunchScreen.storyboard */,
189 | 19803F8A27E5E8AB001930A4 /* Info.plist */,
190 | 199C54AB27E8730900B80DB2 /* gorevler.sqlite */,
191 | 199C549827E8346000B80DB2 /* FMDatabase.h */,
192 | 199C549727E8346000B80DB2 /* FMDatabase.m */,
193 | 199C549127E8345F00B80DB2 /* FMDatabaseAdditions.h */,
194 | 199C549A27E8346000B80DB2 /* FMDatabaseAdditions.m */,
195 | 199C549027E8345F00B80DB2 /* FMDatabasePool.h */,
196 | 199C549327E8345F00B80DB2 /* FMDatabasePool.m */,
197 | 199C549427E8345F00B80DB2 /* FMDatabaseQueue.h */,
198 | 199C549927E8346000B80DB2 /* FMDatabaseQueue.m */,
199 | 199C549527E8346000B80DB2 /* FMDB.h */,
200 | 199C549227E8345F00B80DB2 /* FMResultSet.h */,
201 | 199C549627E8346000B80DB2 /* FMResultSet.m */,
202 | 199C548F27E8345E00B80DB2 /* ToDoApp-Bridging-Header.h */,
203 | );
204 | path = ToDoApp;
205 | sourceTree = "";
206 | };
207 | 19803F9227E5E8AB001930A4 /* ToDoAppTests */ = {
208 | isa = PBXGroup;
209 | children = (
210 | 19803F9327E5E8AB001930A4 /* ToDoAppTests.swift */,
211 | );
212 | path = ToDoAppTests;
213 | sourceTree = "";
214 | };
215 | 19803F9C27E5E8AB001930A4 /* ToDoAppUITests */ = {
216 | isa = PBXGroup;
217 | children = (
218 | 19803F9D27E5E8AB001930A4 /* ToDoAppUITests.swift */,
219 | 19803F9F27E5E8AB001930A4 /* ToDoAppUITestsLaunchTests.swift */,
220 | );
221 | path = ToDoAppUITests;
222 | sourceTree = "";
223 | };
224 | 19803FAC27E5EBC5001930A4 /* Font */ = {
225 | isa = PBXGroup;
226 | children = (
227 | 19803FB527E5EBEA001930A4 /* Roboto-Black.ttf */,
228 | 19803FAE27E5EBE9001930A4 /* Roboto-BlackItalic.ttf */,
229 | 19803FAF27E5EBE9001930A4 /* Roboto-Bold.ttf */,
230 | 19803FAD27E5EBE8001930A4 /* Roboto-BoldItalic.ttf */,
231 | 19803FB027E5EBE9001930A4 /* Roboto-Italic.ttf */,
232 | 19803FB627E5EBEA001930A4 /* Roboto-Light.ttf */,
233 | 19803FB127E5EBE9001930A4 /* Roboto-LightItalic.ttf */,
234 | 19803FB227E5EBE9001930A4 /* Roboto-Medium.ttf */,
235 | 19803FB727E5EBEA001930A4 /* Roboto-MediumItalic.ttf */,
236 | 19803FB327E5EBE9001930A4 /* Roboto-Regular.ttf */,
237 | 19803FB427E5EBE9001930A4 /* Roboto-Thin.ttf */,
238 | 19803FB827E5EBEA001930A4 /* Roboto-ThinItalic.ttf */,
239 | );
240 | path = Font;
241 | sourceTree = "";
242 | };
243 | 199C54A227E8355300B80DB2 /* Frameworks */ = {
244 | isa = PBXGroup;
245 | children = (
246 | 199C54AA27E870A800B80DB2 /* libsqlite3.tbd */,
247 | );
248 | name = Frameworks;
249 | sourceTree = "";
250 | };
251 | 19DF7E5227E7CCD60012C4E9 /* entity */ = {
252 | isa = PBXGroup;
253 | children = (
254 | 19DF7E5027E7CB230012C4E9 /* Task.swift */,
255 | );
256 | path = entity;
257 | sourceTree = "";
258 | };
259 | 19DF7E5327E7CD310012C4E9 /* homepage-module */ = {
260 | isa = PBXGroup;
261 | children = (
262 | 19DF7E5927E7CDD40012C4E9 /* tableview */,
263 | 19DF7E5827E7CDB10012C4E9 /* view */,
264 | 19DF7E5727E7CD8E0012C4E9 /* router */,
265 | 19DF7E5627E7CD7A0012C4E9 /* presenter */,
266 | 19DF7E5527E7CD6D0012C4E9 /* interactor */,
267 | 19DF7E5427E7CD600012C4E9 /* protocols */,
268 | );
269 | path = "homepage-module";
270 | sourceTree = "";
271 | };
272 | 19DF7E5427E7CD600012C4E9 /* protocols */ = {
273 | isa = PBXGroup;
274 | children = (
275 | 19DF7E6127E7DFED0012C4E9 /* HomePageProtocols.swift */,
276 | );
277 | path = protocols;
278 | sourceTree = "";
279 | };
280 | 19DF7E5527E7CD6D0012C4E9 /* interactor */ = {
281 | isa = PBXGroup;
282 | children = (
283 | 19DF7E6327E7E5A80012C4E9 /* HomeInteractor.swift */,
284 | );
285 | path = interactor;
286 | sourceTree = "";
287 | };
288 | 19DF7E5627E7CD7A0012C4E9 /* presenter */ = {
289 | isa = PBXGroup;
290 | children = (
291 | 19DF7E6527E7E7EA0012C4E9 /* HomePresenter.swift */,
292 | );
293 | path = presenter;
294 | sourceTree = "";
295 | };
296 | 19DF7E5727E7CD8E0012C4E9 /* router */ = {
297 | isa = PBXGroup;
298 | children = (
299 | 19DF7E6727E7E91C0012C4E9 /* HomeRouter.swift */,
300 | );
301 | path = router;
302 | sourceTree = "";
303 | };
304 | 19DF7E5827E7CDB10012C4E9 /* view */ = {
305 | isa = PBXGroup;
306 | children = (
307 | 19803F8027E5E8A7001930A4 /* ViewController.swift */,
308 | );
309 | path = view;
310 | sourceTree = "";
311 | };
312 | 19DF7E5927E7CDD40012C4E9 /* tableview */ = {
313 | isa = PBXGroup;
314 | children = (
315 | 19DF7E4E27E7C7970012C4E9 /* TaskTableViewCell.swift */,
316 | );
317 | path = tableview;
318 | sourceTree = "";
319 | };
320 | 19DF7E5A27E7CE130012C4E9 /* taskadd-module */ = {
321 | isa = PBXGroup;
322 | children = (
323 | 19DF7E6027E7CF840012C4E9 /* view */,
324 | 19DF7E5F27E7CF780012C4E9 /* router */,
325 | 19DF7E5E27E7CF430012C4E9 /* presenter */,
326 | 19DF7E5D27E7CF280012C4E9 /* interactor */,
327 | 19DF7E5C27E7CF180012C4E9 /* protocols */,
328 | );
329 | path = "taskadd-module";
330 | sourceTree = "";
331 | };
332 | 19DF7E5B27E7CE6C0012C4E9 /* taskdetail-module */ = {
333 | isa = PBXGroup;
334 | children = (
335 | 19DF7E7027E7EDCD0012C4E9 /* view */,
336 | 19DF7E6F27E7EDC60012C4E9 /* router */,
337 | 19DF7E6D27E7ED9D0012C4E9 /* presenter */,
338 | 19DF7E6E27E7EDAD0012C4E9 /* interactor */,
339 | 19DF7E6C27E7ED910012C4E9 /* protocols */,
340 | );
341 | path = "taskdetail-module";
342 | sourceTree = "";
343 | };
344 | 19DF7E5C27E7CF180012C4E9 /* protocols */ = {
345 | isa = PBXGroup;
346 | children = (
347 | 19DF7E7127E7EE050012C4E9 /* TaskAddProtocols.swift */,
348 | );
349 | path = protocols;
350 | sourceTree = "";
351 | };
352 | 19DF7E5D27E7CF280012C4E9 /* interactor */ = {
353 | isa = PBXGroup;
354 | children = (
355 | 19DF7E7327E7EF960012C4E9 /* TaskAddInteractor.swift */,
356 | );
357 | path = interactor;
358 | sourceTree = "";
359 | };
360 | 19DF7E5E27E7CF430012C4E9 /* presenter */ = {
361 | isa = PBXGroup;
362 | children = (
363 | 19DF7E7527E7F05E0012C4E9 /* TaskAddPresenter.swift */,
364 | );
365 | path = presenter;
366 | sourceTree = "";
367 | };
368 | 19DF7E5F27E7CF780012C4E9 /* router */ = {
369 | isa = PBXGroup;
370 | children = (
371 | 19DF7E7727E7F0B10012C4E9 /* TasAddRouter.swift */,
372 | );
373 | path = router;
374 | sourceTree = "";
375 | };
376 | 19DF7E6027E7CF840012C4E9 /* view */ = {
377 | isa = PBXGroup;
378 | children = (
379 | 19803FC527E603FE001930A4 /* AddTaskViewController.swift */,
380 | );
381 | path = view;
382 | sourceTree = "";
383 | };
384 | 19DF7E6C27E7ED910012C4E9 /* protocols */ = {
385 | isa = PBXGroup;
386 | children = (
387 | 19DF7E7927E80D9A0012C4E9 /* TaskDetailProtocols.swift */,
388 | );
389 | path = protocols;
390 | sourceTree = "";
391 | };
392 | 19DF7E6D27E7ED9D0012C4E9 /* presenter */ = {
393 | isa = PBXGroup;
394 | children = (
395 | 19DF7E7D27E810540012C4E9 /* TaskDetailPresenter.swift */,
396 | );
397 | path = presenter;
398 | sourceTree = "";
399 | };
400 | 19DF7E6E27E7EDAD0012C4E9 /* interactor */ = {
401 | isa = PBXGroup;
402 | children = (
403 | 19DF7E7B27E80FC00012C4E9 /* TaskDetailInteractor.swift */,
404 | );
405 | path = interactor;
406 | sourceTree = "";
407 | };
408 | 19DF7E6F27E7EDC60012C4E9 /* router */ = {
409 | isa = PBXGroup;
410 | children = (
411 | 19DF7E7F27E810B10012C4E9 /* TaskDetailRouter.swift */,
412 | );
413 | path = router;
414 | sourceTree = "";
415 | };
416 | 19DF7E7027E7EDCD0012C4E9 /* view */ = {
417 | isa = PBXGroup;
418 | children = (
419 | 19DF7E6927E7ED740012C4E9 /* TaskDetailViewController.swift */,
420 | );
421 | path = view;
422 | sourceTree = "";
423 | };
424 | /* End PBXGroup section */
425 |
426 | /* Begin PBXNativeTarget section */
427 | 19803F7827E5E8A7001930A4 /* ToDoApp */ = {
428 | isa = PBXNativeTarget;
429 | buildConfigurationList = 19803FA327E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoApp" */;
430 | buildPhases = (
431 | 19803F7527E5E8A7001930A4 /* Sources */,
432 | 19803F7627E5E8A7001930A4 /* Frameworks */,
433 | 19803F7727E5E8A7001930A4 /* Resources */,
434 | );
435 | buildRules = (
436 | );
437 | dependencies = (
438 | );
439 | name = ToDoApp;
440 | productName = ToDoApp;
441 | productReference = 19803F7927E5E8A7001930A4 /* ToDoApp.app */;
442 | productType = "com.apple.product-type.application";
443 | };
444 | 19803F8E27E5E8AB001930A4 /* ToDoAppTests */ = {
445 | isa = PBXNativeTarget;
446 | buildConfigurationList = 19803FA627E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoAppTests" */;
447 | buildPhases = (
448 | 19803F8B27E5E8AB001930A4 /* Sources */,
449 | 19803F8C27E5E8AB001930A4 /* Frameworks */,
450 | 19803F8D27E5E8AB001930A4 /* Resources */,
451 | );
452 | buildRules = (
453 | );
454 | dependencies = (
455 | 19803F9127E5E8AB001930A4 /* PBXTargetDependency */,
456 | );
457 | name = ToDoAppTests;
458 | productName = ToDoAppTests;
459 | productReference = 19803F8F27E5E8AB001930A4 /* ToDoAppTests.xctest */;
460 | productType = "com.apple.product-type.bundle.unit-test";
461 | };
462 | 19803F9827E5E8AB001930A4 /* ToDoAppUITests */ = {
463 | isa = PBXNativeTarget;
464 | buildConfigurationList = 19803FA927E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoAppUITests" */;
465 | buildPhases = (
466 | 19803F9527E5E8AB001930A4 /* Sources */,
467 | 19803F9627E5E8AB001930A4 /* Frameworks */,
468 | 19803F9727E5E8AB001930A4 /* Resources */,
469 | );
470 | buildRules = (
471 | );
472 | dependencies = (
473 | 19803F9B27E5E8AB001930A4 /* PBXTargetDependency */,
474 | );
475 | name = ToDoAppUITests;
476 | productName = ToDoAppUITests;
477 | productReference = 19803F9927E5E8AB001930A4 /* ToDoAppUITests.xctest */;
478 | productType = "com.apple.product-type.bundle.ui-testing";
479 | };
480 | /* End PBXNativeTarget section */
481 |
482 | /* Begin PBXProject section */
483 | 19803F7127E5E8A7001930A4 /* Project object */ = {
484 | isa = PBXProject;
485 | attributes = {
486 | BuildIndependentTargetsInParallel = 1;
487 | LastSwiftUpdateCheck = 1320;
488 | LastUpgradeCheck = 1320;
489 | TargetAttributes = {
490 | 19803F7827E5E8A7001930A4 = {
491 | CreatedOnToolsVersion = 13.2.1;
492 | LastSwiftMigration = 1320;
493 | };
494 | 19803F8E27E5E8AB001930A4 = {
495 | CreatedOnToolsVersion = 13.2.1;
496 | TestTargetID = 19803F7827E5E8A7001930A4;
497 | };
498 | 19803F9827E5E8AB001930A4 = {
499 | CreatedOnToolsVersion = 13.2.1;
500 | TestTargetID = 19803F7827E5E8A7001930A4;
501 | };
502 | };
503 | };
504 | buildConfigurationList = 19803F7427E5E8A7001930A4 /* Build configuration list for PBXProject "ToDoApp" */;
505 | compatibilityVersion = "Xcode 13.0";
506 | developmentRegion = en;
507 | hasScannedForEncodings = 0;
508 | knownRegions = (
509 | en,
510 | Base,
511 | );
512 | mainGroup = 19803F7027E5E8A7001930A4;
513 | productRefGroup = 19803F7A27E5E8A7001930A4 /* Products */;
514 | projectDirPath = "";
515 | projectRoot = "";
516 | targets = (
517 | 19803F7827E5E8A7001930A4 /* ToDoApp */,
518 | 19803F8E27E5E8AB001930A4 /* ToDoAppTests */,
519 | 19803F9827E5E8AB001930A4 /* ToDoAppUITests */,
520 | );
521 | };
522 | /* End PBXProject section */
523 |
524 | /* Begin PBXResourcesBuildPhase section */
525 | 19803F7727E5E8A7001930A4 /* Resources */ = {
526 | isa = PBXResourcesBuildPhase;
527 | buildActionMask = 2147483647;
528 | files = (
529 | 19803FC427E5EBEA001930A4 /* Roboto-ThinItalic.ttf in Resources */,
530 | 19803F8927E5E8AB001930A4 /* LaunchScreen.storyboard in Resources */,
531 | 19803F8627E5E8AB001930A4 /* Assets.xcassets in Resources */,
532 | 19803FBF27E5EBEA001930A4 /* Roboto-Regular.ttf in Resources */,
533 | 19803FBD27E5EBEA001930A4 /* Roboto-LightItalic.ttf in Resources */,
534 | 199C54AC27E8730900B80DB2 /* gorevler.sqlite in Resources */,
535 | 19803FC327E5EBEA001930A4 /* Roboto-MediumItalic.ttf in Resources */,
536 | 19803FC027E5EBEA001930A4 /* Roboto-Thin.ttf in Resources */,
537 | 19803FBB27E5EBEA001930A4 /* Roboto-Bold.ttf in Resources */,
538 | 19803FBA27E5EBEA001930A4 /* Roboto-BlackItalic.ttf in Resources */,
539 | 19803FBC27E5EBEA001930A4 /* Roboto-Italic.ttf in Resources */,
540 | 19803FB927E5EBEA001930A4 /* Roboto-BoldItalic.ttf in Resources */,
541 | 19803FC227E5EBEA001930A4 /* Roboto-Light.ttf in Resources */,
542 | 19803F8427E5E8A7001930A4 /* Main.storyboard in Resources */,
543 | 19803FBE27E5EBEA001930A4 /* Roboto-Medium.ttf in Resources */,
544 | 19803FC127E5EBEA001930A4 /* Roboto-Black.ttf in Resources */,
545 | );
546 | runOnlyForDeploymentPostprocessing = 0;
547 | };
548 | 19803F8D27E5E8AB001930A4 /* Resources */ = {
549 | isa = PBXResourcesBuildPhase;
550 | buildActionMask = 2147483647;
551 | files = (
552 | );
553 | runOnlyForDeploymentPostprocessing = 0;
554 | };
555 | 19803F9727E5E8AB001930A4 /* Resources */ = {
556 | isa = PBXResourcesBuildPhase;
557 | buildActionMask = 2147483647;
558 | files = (
559 | );
560 | runOnlyForDeploymentPostprocessing = 0;
561 | };
562 | /* End PBXResourcesBuildPhase section */
563 |
564 | /* Begin PBXSourcesBuildPhase section */
565 | 19803F7527E5E8A7001930A4 /* Sources */ = {
566 | isa = PBXSourcesBuildPhase;
567 | buildActionMask = 2147483647;
568 | files = (
569 | 19DF7E7827E7F0B10012C4E9 /* TasAddRouter.swift in Sources */,
570 | 19803F8127E5E8A7001930A4 /* ViewController.swift in Sources */,
571 | 19DF7E7C27E80FC00012C4E9 /* TaskDetailInteractor.swift in Sources */,
572 | 19803FC627E603FE001930A4 /* AddTaskViewController.swift in Sources */,
573 | 19DF7E4F27E7C7970012C4E9 /* TaskTableViewCell.swift in Sources */,
574 | 19DF7E6427E7E5A80012C4E9 /* HomeInteractor.swift in Sources */,
575 | 19803F7D27E5E8A7001930A4 /* AppDelegate.swift in Sources */,
576 | 19DF7E5127E7CB230012C4E9 /* Task.swift in Sources */,
577 | 19DF7E7227E7EE050012C4E9 /* TaskAddProtocols.swift in Sources */,
578 | 199C549D27E8346000B80DB2 /* FMDatabase.m in Sources */,
579 | 199C549C27E8346000B80DB2 /* FMResultSet.m in Sources */,
580 | 19DF7E8027E810B10012C4E9 /* TaskDetailRouter.swift in Sources */,
581 | 199C549E27E8346000B80DB2 /* FMDatabaseQueue.m in Sources */,
582 | 19DF7E6A27E7ED740012C4E9 /* TaskDetailViewController.swift in Sources */,
583 | 19DF7E6627E7E7EA0012C4E9 /* HomePresenter.swift in Sources */,
584 | 19DF7E7427E7EF960012C4E9 /* TaskAddInteractor.swift in Sources */,
585 | 19DF7E6227E7DFED0012C4E9 /* HomePageProtocols.swift in Sources */,
586 | 19803F7F27E5E8A7001930A4 /* SceneDelegate.swift in Sources */,
587 | 19DF7E7E27E810540012C4E9 /* TaskDetailPresenter.swift in Sources */,
588 | 19DF7E6827E7E91C0012C4E9 /* HomeRouter.swift in Sources */,
589 | 199C549B27E8346000B80DB2 /* FMDatabasePool.m in Sources */,
590 | 19DF7E7627E7F05E0012C4E9 /* TaskAddPresenter.swift in Sources */,
591 | 19DF7E7A27E80D9A0012C4E9 /* TaskDetailProtocols.swift in Sources */,
592 | 199C549F27E8346000B80DB2 /* FMDatabaseAdditions.m in Sources */,
593 | );
594 | runOnlyForDeploymentPostprocessing = 0;
595 | };
596 | 19803F8B27E5E8AB001930A4 /* Sources */ = {
597 | isa = PBXSourcesBuildPhase;
598 | buildActionMask = 2147483647;
599 | files = (
600 | 19803F9427E5E8AB001930A4 /* ToDoAppTests.swift in Sources */,
601 | );
602 | runOnlyForDeploymentPostprocessing = 0;
603 | };
604 | 19803F9527E5E8AB001930A4 /* Sources */ = {
605 | isa = PBXSourcesBuildPhase;
606 | buildActionMask = 2147483647;
607 | files = (
608 | 19803FA027E5E8AB001930A4 /* ToDoAppUITestsLaunchTests.swift in Sources */,
609 | 19803F9E27E5E8AB001930A4 /* ToDoAppUITests.swift in Sources */,
610 | );
611 | runOnlyForDeploymentPostprocessing = 0;
612 | };
613 | /* End PBXSourcesBuildPhase section */
614 |
615 | /* Begin PBXTargetDependency section */
616 | 19803F9127E5E8AB001930A4 /* PBXTargetDependency */ = {
617 | isa = PBXTargetDependency;
618 | target = 19803F7827E5E8A7001930A4 /* ToDoApp */;
619 | targetProxy = 19803F9027E5E8AB001930A4 /* PBXContainerItemProxy */;
620 | };
621 | 19803F9B27E5E8AB001930A4 /* PBXTargetDependency */ = {
622 | isa = PBXTargetDependency;
623 | target = 19803F7827E5E8A7001930A4 /* ToDoApp */;
624 | targetProxy = 19803F9A27E5E8AB001930A4 /* PBXContainerItemProxy */;
625 | };
626 | /* End PBXTargetDependency section */
627 |
628 | /* Begin PBXVariantGroup section */
629 | 19803F8227E5E8A7001930A4 /* Main.storyboard */ = {
630 | isa = PBXVariantGroup;
631 | children = (
632 | 19803F8327E5E8A7001930A4 /* Base */,
633 | );
634 | name = Main.storyboard;
635 | sourceTree = "";
636 | };
637 | 19803F8727E5E8AB001930A4 /* LaunchScreen.storyboard */ = {
638 | isa = PBXVariantGroup;
639 | children = (
640 | 19803F8827E5E8AB001930A4 /* Base */,
641 | );
642 | name = LaunchScreen.storyboard;
643 | sourceTree = "";
644 | };
645 | /* End PBXVariantGroup section */
646 |
647 | /* Begin XCBuildConfiguration section */
648 | 19803FA127E5E8AB001930A4 /* Debug */ = {
649 | isa = XCBuildConfiguration;
650 | buildSettings = {
651 | ALWAYS_SEARCH_USER_PATHS = NO;
652 | CLANG_ANALYZER_NONNULL = YES;
653 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
654 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
655 | CLANG_CXX_LIBRARY = "libc++";
656 | CLANG_ENABLE_MODULES = YES;
657 | CLANG_ENABLE_OBJC_ARC = YES;
658 | CLANG_ENABLE_OBJC_WEAK = YES;
659 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
660 | CLANG_WARN_BOOL_CONVERSION = YES;
661 | CLANG_WARN_COMMA = YES;
662 | CLANG_WARN_CONSTANT_CONVERSION = YES;
663 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
664 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
665 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
666 | CLANG_WARN_EMPTY_BODY = YES;
667 | CLANG_WARN_ENUM_CONVERSION = YES;
668 | CLANG_WARN_INFINITE_RECURSION = YES;
669 | CLANG_WARN_INT_CONVERSION = YES;
670 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
671 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
672 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
673 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
674 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
675 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
676 | CLANG_WARN_STRICT_PROTOTYPES = YES;
677 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
678 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
679 | CLANG_WARN_UNREACHABLE_CODE = YES;
680 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
681 | COPY_PHASE_STRIP = NO;
682 | DEBUG_INFORMATION_FORMAT = dwarf;
683 | ENABLE_STRICT_OBJC_MSGSEND = YES;
684 | ENABLE_TESTABILITY = YES;
685 | GCC_C_LANGUAGE_STANDARD = gnu11;
686 | GCC_DYNAMIC_NO_PIC = NO;
687 | GCC_NO_COMMON_BLOCKS = YES;
688 | GCC_OPTIMIZATION_LEVEL = 0;
689 | GCC_PREPROCESSOR_DEFINITIONS = (
690 | "DEBUG=1",
691 | "$(inherited)",
692 | );
693 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
694 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
695 | GCC_WARN_UNDECLARED_SELECTOR = YES;
696 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
697 | GCC_WARN_UNUSED_FUNCTION = YES;
698 | GCC_WARN_UNUSED_VARIABLE = YES;
699 | IPHONEOS_DEPLOYMENT_TARGET = 15.2;
700 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
701 | MTL_FAST_MATH = YES;
702 | ONLY_ACTIVE_ARCH = YES;
703 | SDKROOT = iphoneos;
704 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
705 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
706 | };
707 | name = Debug;
708 | };
709 | 19803FA227E5E8AB001930A4 /* Release */ = {
710 | isa = XCBuildConfiguration;
711 | buildSettings = {
712 | ALWAYS_SEARCH_USER_PATHS = NO;
713 | CLANG_ANALYZER_NONNULL = YES;
714 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
715 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
716 | CLANG_CXX_LIBRARY = "libc++";
717 | CLANG_ENABLE_MODULES = YES;
718 | CLANG_ENABLE_OBJC_ARC = YES;
719 | CLANG_ENABLE_OBJC_WEAK = YES;
720 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
721 | CLANG_WARN_BOOL_CONVERSION = YES;
722 | CLANG_WARN_COMMA = YES;
723 | CLANG_WARN_CONSTANT_CONVERSION = YES;
724 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
725 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
726 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
727 | CLANG_WARN_EMPTY_BODY = YES;
728 | CLANG_WARN_ENUM_CONVERSION = YES;
729 | CLANG_WARN_INFINITE_RECURSION = YES;
730 | CLANG_WARN_INT_CONVERSION = YES;
731 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
732 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
733 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
734 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
735 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
736 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
737 | CLANG_WARN_STRICT_PROTOTYPES = YES;
738 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
739 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
740 | CLANG_WARN_UNREACHABLE_CODE = YES;
741 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
742 | COPY_PHASE_STRIP = NO;
743 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
744 | ENABLE_NS_ASSERTIONS = NO;
745 | ENABLE_STRICT_OBJC_MSGSEND = YES;
746 | GCC_C_LANGUAGE_STANDARD = gnu11;
747 | GCC_NO_COMMON_BLOCKS = YES;
748 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
749 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
750 | GCC_WARN_UNDECLARED_SELECTOR = YES;
751 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
752 | GCC_WARN_UNUSED_FUNCTION = YES;
753 | GCC_WARN_UNUSED_VARIABLE = YES;
754 | IPHONEOS_DEPLOYMENT_TARGET = 15.2;
755 | MTL_ENABLE_DEBUG_INFO = NO;
756 | MTL_FAST_MATH = YES;
757 | SDKROOT = iphoneos;
758 | SWIFT_COMPILATION_MODE = wholemodule;
759 | SWIFT_OPTIMIZATION_LEVEL = "-O";
760 | VALIDATE_PRODUCT = YES;
761 | };
762 | name = Release;
763 | };
764 | 19803FA427E5E8AB001930A4 /* Debug */ = {
765 | isa = XCBuildConfiguration;
766 | buildSettings = {
767 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
768 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
769 | CLANG_ENABLE_MODULES = YES;
770 | CODE_SIGN_STYLE = Automatic;
771 | CURRENT_PROJECT_VERSION = 1;
772 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
773 | GENERATE_INFOPLIST_FILE = YES;
774 | INFOPLIST_FILE = ToDoApp/Info.plist;
775 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
776 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
777 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
778 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
779 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
780 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
781 | LD_RUNPATH_SEARCH_PATHS = (
782 | "$(inherited)",
783 | "@executable_path/Frameworks",
784 | );
785 | MARKETING_VERSION = 1.0;
786 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoApp;
787 | PRODUCT_NAME = "$(TARGET_NAME)";
788 | SWIFT_EMIT_LOC_STRINGS = YES;
789 | SWIFT_OBJC_BRIDGING_HEADER = "ToDoApp/ToDoApp-Bridging-Header.h";
790 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
791 | SWIFT_VERSION = 5.0;
792 | TARGETED_DEVICE_FAMILY = "1,2";
793 | };
794 | name = Debug;
795 | };
796 | 19803FA527E5E8AB001930A4 /* Release */ = {
797 | isa = XCBuildConfiguration;
798 | buildSettings = {
799 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
800 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
801 | CLANG_ENABLE_MODULES = YES;
802 | CODE_SIGN_STYLE = Automatic;
803 | CURRENT_PROJECT_VERSION = 1;
804 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
805 | GENERATE_INFOPLIST_FILE = YES;
806 | INFOPLIST_FILE = ToDoApp/Info.plist;
807 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
808 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
809 | INFOPLIST_KEY_UIMainStoryboardFile = Main;
810 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
811 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
812 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
813 | LD_RUNPATH_SEARCH_PATHS = (
814 | "$(inherited)",
815 | "@executable_path/Frameworks",
816 | );
817 | MARKETING_VERSION = 1.0;
818 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoApp;
819 | PRODUCT_NAME = "$(TARGET_NAME)";
820 | SWIFT_EMIT_LOC_STRINGS = YES;
821 | SWIFT_OBJC_BRIDGING_HEADER = "ToDoApp/ToDoApp-Bridging-Header.h";
822 | SWIFT_VERSION = 5.0;
823 | TARGETED_DEVICE_FAMILY = "1,2";
824 | };
825 | name = Release;
826 | };
827 | 19803FA727E5E8AB001930A4 /* Debug */ = {
828 | isa = XCBuildConfiguration;
829 | buildSettings = {
830 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
831 | BUNDLE_LOADER = "$(TEST_HOST)";
832 | CODE_SIGN_STYLE = Automatic;
833 | CURRENT_PROJECT_VERSION = 1;
834 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
835 | GENERATE_INFOPLIST_FILE = YES;
836 | IPHONEOS_DEPLOYMENT_TARGET = 15.2;
837 | MARKETING_VERSION = 1.0;
838 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoAppTests;
839 | PRODUCT_NAME = "$(TARGET_NAME)";
840 | SWIFT_EMIT_LOC_STRINGS = NO;
841 | SWIFT_VERSION = 5.0;
842 | TARGETED_DEVICE_FAMILY = "1,2";
843 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ToDoApp.app/ToDoApp";
844 | };
845 | name = Debug;
846 | };
847 | 19803FA827E5E8AB001930A4 /* Release */ = {
848 | isa = XCBuildConfiguration;
849 | buildSettings = {
850 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
851 | BUNDLE_LOADER = "$(TEST_HOST)";
852 | CODE_SIGN_STYLE = Automatic;
853 | CURRENT_PROJECT_VERSION = 1;
854 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
855 | GENERATE_INFOPLIST_FILE = YES;
856 | IPHONEOS_DEPLOYMENT_TARGET = 15.2;
857 | MARKETING_VERSION = 1.0;
858 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoAppTests;
859 | PRODUCT_NAME = "$(TARGET_NAME)";
860 | SWIFT_EMIT_LOC_STRINGS = NO;
861 | SWIFT_VERSION = 5.0;
862 | TARGETED_DEVICE_FAMILY = "1,2";
863 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ToDoApp.app/ToDoApp";
864 | };
865 | name = Release;
866 | };
867 | 19803FAA27E5E8AB001930A4 /* Debug */ = {
868 | isa = XCBuildConfiguration;
869 | buildSettings = {
870 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
871 | CODE_SIGN_STYLE = Automatic;
872 | CURRENT_PROJECT_VERSION = 1;
873 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
874 | GENERATE_INFOPLIST_FILE = YES;
875 | MARKETING_VERSION = 1.0;
876 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoAppUITests;
877 | PRODUCT_NAME = "$(TARGET_NAME)";
878 | SWIFT_EMIT_LOC_STRINGS = NO;
879 | SWIFT_VERSION = 5.0;
880 | TARGETED_DEVICE_FAMILY = "1,2";
881 | TEST_TARGET_NAME = ToDoApp;
882 | };
883 | name = Debug;
884 | };
885 | 19803FAB27E5E8AB001930A4 /* Release */ = {
886 | isa = XCBuildConfiguration;
887 | buildSettings = {
888 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
889 | CODE_SIGN_STYLE = Automatic;
890 | CURRENT_PROJECT_VERSION = 1;
891 | DEVELOPMENT_TEAM = 8G6U7HNLTQ;
892 | GENERATE_INFOPLIST_FILE = YES;
893 | MARKETING_VERSION = 1.0;
894 | PRODUCT_BUNDLE_IDENTIFIER = com.info.ToDoAppUITests;
895 | PRODUCT_NAME = "$(TARGET_NAME)";
896 | SWIFT_EMIT_LOC_STRINGS = NO;
897 | SWIFT_VERSION = 5.0;
898 | TARGETED_DEVICE_FAMILY = "1,2";
899 | TEST_TARGET_NAME = ToDoApp;
900 | };
901 | name = Release;
902 | };
903 | /* End XCBuildConfiguration section */
904 |
905 | /* Begin XCConfigurationList section */
906 | 19803F7427E5E8A7001930A4 /* Build configuration list for PBXProject "ToDoApp" */ = {
907 | isa = XCConfigurationList;
908 | buildConfigurations = (
909 | 19803FA127E5E8AB001930A4 /* Debug */,
910 | 19803FA227E5E8AB001930A4 /* Release */,
911 | );
912 | defaultConfigurationIsVisible = 0;
913 | defaultConfigurationName = Release;
914 | };
915 | 19803FA327E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoApp" */ = {
916 | isa = XCConfigurationList;
917 | buildConfigurations = (
918 | 19803FA427E5E8AB001930A4 /* Debug */,
919 | 19803FA527E5E8AB001930A4 /* Release */,
920 | );
921 | defaultConfigurationIsVisible = 0;
922 | defaultConfigurationName = Release;
923 | };
924 | 19803FA627E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoAppTests" */ = {
925 | isa = XCConfigurationList;
926 | buildConfigurations = (
927 | 19803FA727E5E8AB001930A4 /* Debug */,
928 | 19803FA827E5E8AB001930A4 /* Release */,
929 | );
930 | defaultConfigurationIsVisible = 0;
931 | defaultConfigurationName = Release;
932 | };
933 | 19803FA927E5E8AB001930A4 /* Build configuration list for PBXNativeTarget "ToDoAppUITests" */ = {
934 | isa = XCConfigurationList;
935 | buildConfigurations = (
936 | 19803FAA27E5E8AB001930A4 /* Debug */,
937 | 19803FAB27E5E8AB001930A4 /* Release */,
938 | );
939 | defaultConfigurationIsVisible = 0;
940 | defaultConfigurationName = Release;
941 | };
942 | /* End XCConfigurationList section */
943 | };
944 | rootObject = 19803F7127E5E8A7001930A4 /* Project object */;
945 | }
946 |
--------------------------------------------------------------------------------