diff --git a/Client/iOS/TodoList/AppDelegate.swift b/Client/iOS/TodoList/AppDelegate.swift
index 47ee1edae..df3d8fb6e 100644
--- a/Client/iOS/TodoList/AppDelegate.swift
+++ b/Client/iOS/TodoList/AppDelegate.swift
@@ -10,9 +10,20 @@ import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
- static let middleWare = CardDataMiddleWare {
- DebugDataTask(api: Team13API())
+ static let dataTask = DataTask(api: Team13API())
+ static let middleWare = CardDataMiddleWare(persistenceProvider: BoardPersistenceProvider()) {
+ dataTask
}
+ func applicationDidFinishLaunching(_ application: UIApplication) {
+ // TODO:- 사용자 쿠키를 받아오지 못했을때 처리
+ Self.dataTask?.fetchUser(completionHandler: { result in
+ switch result {
+ case .success:
+ break
+ case .failure:
+ break
+ }
+ })
+ }
}
-
diff --git a/Client/iOS/TodoList/Base.lproj/Main.storyboard b/Client/iOS/TodoList/Base.lproj/Main.storyboard
index 126d29559..1d344e225 100644
--- a/Client/iOS/TodoList/Base.lproj/Main.storyboard
+++ b/Client/iOS/TodoList/Base.lproj/Main.storyboard
@@ -22,6 +22,7 @@
+
@@ -48,6 +49,7 @@
+
@@ -106,7 +108,8 @@
-
+
+
@@ -152,6 +155,7 @@
+
@@ -179,9 +183,9 @@
-
+
-
+
@@ -254,7 +258,7 @@
-
+
@@ -329,7 +333,7 @@
-
+
diff --git a/Client/iOS/TodoList/Cells/TodoTableViewCell.swift b/Client/iOS/TodoList/Cells/TodoTableViewCell.swift
index 59dc9e739..4890fc565 100644
--- a/Client/iOS/TodoList/Cells/TodoTableViewCell.swift
+++ b/Client/iOS/TodoList/Cells/TodoTableViewCell.swift
@@ -20,7 +20,7 @@ class TodoTableViewCell: UITableViewCell {
roundedView.layer.masksToBounds = true
}
- func applyTextAllLabels(data card: CardData) {
+ func applyTextAllLabels(data card: Card) {
setTitleLabelAttribute(card.title)
setContentLabelAttribute(card.contents)
}
diff --git a/Client/iOS/TodoList/Cells/TodoTableViewCell.xib b/Client/iOS/TodoList/Cells/TodoTableViewCell.xib
index 4ae39d680..ea2caf4b4 100644
--- a/Client/iOS/TodoList/Cells/TodoTableViewCell.xib
+++ b/Client/iOS/TodoList/Cells/TodoTableViewCell.xib
@@ -20,7 +20,7 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
+
@@ -94,7 +84,7 @@
-
+
diff --git a/Client/iOS/TodoList/DB/PersistenceProvider.swift b/Client/iOS/TodoList/DB/PersistenceProvider.swift
index 9bff4baf0..5aac95e11 100644
--- a/Client/iOS/TodoList/DB/PersistenceProvider.swift
+++ b/Client/iOS/TodoList/DB/PersistenceProvider.swift
@@ -3,9 +3,9 @@ import CoreData
// MARK:- Cards
struct Card {
- let cardId: Int
- let cardTitle: String
- let cardContent: String
+ let id: Int
+ let title: String
+ let contents: String
let boardName: String
}
@@ -16,22 +16,28 @@ enum BoardType: CustomStringConvertible {
case done
var description: String {
- return "\(self)"
+ switch self {
+ case .todo:
+ return "TODO"
+ case .progress:
+ return "DOING"
+ case .done:
+ return "DONE"
+ default:
+ return ""
+ }
}
}
// MARK:- DataManager
protocol PersistenceProvider {
func insertCard(boardType: BoardType, id: Int, title: String, content: String)
+ func insertBoard(type: BoardType, cards: [Card])
func fetchAllCard(where boardType: BoardType) -> [Card]
}
class BoardPersistenceProvider: PersistenceProvider {
- static var shared = BoardPersistenceProvider()
-
- private init() {}
-
private lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Model")
container.loadPersistentStores { description, error in
@@ -50,12 +56,23 @@ class BoardPersistenceProvider: PersistenceProvider {
return NSEntityDescription.entity(forEntityName: "TaskBoard", in: context)
}
+ func insertBoard(type: BoardType, cards: [Card]) {
+ let fetchAllCard = fetchAllCard(where: type)
+ for card in cards {
+ if fetchAllCard.contains(where: { $0.id == card.id }) {
+ // TODO:- id 가 같지만 수정되어 필드값이 하나라도 다를 수 있다 -> 모든 필드가 같은지 비교 필요
+ continue
+ }
+ insertCard(boardType: type, id: card.id, title: card.title, content: card.contents)
+ }
+ }
+
func insertCard(boardType: BoardType, id: Int, title: String, content: String) {
guard let entity = entity else {
return
}
let object = NSManagedObject(entity: entity, insertInto: context)
- object.setValue(boardType, forKey: "type")
+ object.setValue(boardType.description, forKey: "type")
object.setValue(id, forKey: "cardId")
object.setValue(content, forKey: "content")
object.setValue(title, forKey: "title")
@@ -66,7 +83,8 @@ class BoardPersistenceProvider: PersistenceProvider {
do {
let fetchResults = try context.fetch(TaskBoard.fetchRequest()) as! [TaskBoard]
let results = fetchResults
- .map{ Card.init(cardId: Int($0.cardId), cardTitle: $0.title!, cardContent: $0.content!, boardName: $0.type!) }
+ .map{ Card(id: Int($0.cardId), title: $0.title!, contents: $0.content!, boardName: $0.type!) }
+
if boardType == .all {
return results
}
diff --git a/Client/iOS/TodoList/Network/CardsFetchingDataTask.swift b/Client/iOS/TodoList/Network/CardsFetchingDataTask.swift
index 2ddcbf274..25fdcc652 100644
--- a/Client/iOS/TodoList/Network/CardsFetchingDataTask.swift
+++ b/Client/iOS/TodoList/Network/CardsFetchingDataTask.swift
@@ -11,8 +11,14 @@ struct Team13API: ServerAPI {
let endpoint: String = "http://13.125.216.180:8080"
}
+protocol APIService {
+ func fetchUser(completionHandler: @escaping (Result) -> Void)
+ func fetchAll(dataType: T.Type, completionHandler: @escaping (Result) -> Void)
+ func requestDelete(parameter: Int, completionHandler: @escaping (Result) -> Void)
+}
+
-class DataTask: SessionDataTask {
+class DataTask: SessionDataTask, APIService {
private let encoder = JSONEncoder()
private let decoder = JSONDecoder()
private let api: ServerAPI
@@ -78,6 +84,29 @@ class DataTask: SessionDataTask {
}.resume()
}
+ func requestDelete(parameter: Int, completionHandler: @escaping (Result) -> Void) {
+ guard var url = api.toURL(path: .all) else {
+ completionHandler(.failure(.invalidURL))
+ return
+ }
+
+ url.appendPathComponent("\(parameter)")
+ var request = URLRequest(url: url)
+ request.httpMethod = "DELETE"
+
+ self.session.dataTask(with: request) { data, response, error in
+ guard
+ let data = data,
+ let cardResponse = try? self.decoder.decode(CardAPIResponse.self, from: data)
+ else {
+ completionHandler(.failure(.notConnect))
+ return
+ }
+
+ completionHandler(.success(cardResponse.cardId))
+ }.resume()
+ }
+
private func makeRequestContainCookie(with url: URL) -> URLRequest? {
var request = URLRequest(url: url)
guard let baseUrl = api.toURL(path: .base),
diff --git a/Client/iOS/TodoList/Network/CardsFetchingDebugDataTask.swift b/Client/iOS/TodoList/Network/CardsFetchingDebugDataTask.swift
index dfe8b1109..1ea960700 100644
--- a/Client/iOS/TodoList/Network/CardsFetchingDebugDataTask.swift
+++ b/Client/iOS/TodoList/Network/CardsFetchingDebugDataTask.swift
@@ -47,6 +47,29 @@ class DebugDataTask: SessionDataTask {
}.resume()
}
+ func requestDelete(parameter: Int, completionHandler: @escaping (Result) -> Void) {
+ guard var url = api.toURL(path: .all) else {
+ completionHandler(.failure(.invalidURL))
+ return
+ }
+
+ url.appendPathComponent("\(parameter)")
+ var request = URLRequest(url: url)
+ request.httpMethod = "DELETE"
+
+ self.session.dataTask(with: request) { data, response, error in
+ guard
+ let data = data,
+ let cardResponse = try? self.decoder.decode(CardAPIResponse.self, from: data)
+ else {
+ completionHandler(.failure(.notConnect))
+ return
+ }
+
+ completionHandler(.success(cardResponse.cardId))
+ }
+ }
+
private func makeURLComponents(from string: String? = nil, using parameter: [String: String]? = nil) -> URLComponents? {
if let string = string {
diff --git a/Client/iOS/TodoList/Network/ResourcesNetwork/CardAPIResponse.swift b/Client/iOS/TodoList/Network/ResourcesNetwork/CardAPIResponse.swift
new file mode 100644
index 000000000..120a0964b
--- /dev/null
+++ b/Client/iOS/TodoList/Network/ResourcesNetwork/CardAPIResponse.swift
@@ -0,0 +1,5 @@
+import Foundation
+
+struct CardAPIResponse: Codable {
+ var cardId: Int
+}
diff --git a/Client/iOS/TodoList/Network/ResourcesNetwork/CardMap.swift b/Client/iOS/TodoList/Network/ResourcesNetwork/CardMap.swift
index 8536d9ce0..c2c9f144d 100644
--- a/Client/iOS/TodoList/Network/ResourcesNetwork/CardMap.swift
+++ b/Client/iOS/TodoList/Network/ResourcesNetwork/CardMap.swift
@@ -11,6 +11,6 @@ struct CardMap: Codable {
var cardMap: TodoList
struct TodoList: Codable {
- var todo: [CardData]
+ var TODO: [CardData]
}
}
diff --git a/Client/iOS/TodoList/Repository/CardDataMiddleWare.swift b/Client/iOS/TodoList/Repository/CardDataMiddleWare.swift
index 27a9c674c..4e168b7c2 100644
--- a/Client/iOS/TodoList/Repository/CardDataMiddleWare.swift
+++ b/Client/iOS/TodoList/Repository/CardDataMiddleWare.swift
@@ -2,11 +2,9 @@ import UIKit
class CardDataMiddleWare {
- private var fetchResultInBoard = [TodoBoard: Result<[CardData], DataTaskError>]() {
+ private var fetchResultInBoard = [TodoBoard: Result<[Card], DataTaskError>]() {
willSet {
-
for board in newValue.keys {
-
guard let result = newValue[board] else { continue }
NotificationCenter
.default
@@ -15,42 +13,57 @@ class CardDataMiddleWare {
object: self,
userInfo: ["result":result]
)
-
}
}
}
- private var dataTask: DebugDataTask?
+ private var dataTask: APIService?
+ private let persistenceProvider: PersistenceProvider?
- init(_ dataTaskGenerator: ()->DebugDataTask?) {
+ init(persistenceProvider: PersistenceProvider, dataTaskGenerator: ()-> APIService?) {
+ self.persistenceProvider = persistenceProvider
self.dataTask = dataTaskGenerator()
}
func fetchAllCards() {
+ guard let resultFromCoredata = persistenceProvider?.fetchAllCard(where: .all) else {
+ return
+ }
+
dataTask?.fetchAll(dataType: CardMap.self) { [weak self] (result: Result) in
-
guard let self = self else { return }
-
+
for board in TodoBoard.allCases {
-
switch result {
-
case .success(let cardMap):
-
- self.fetchResultInBoard[board] = Result.success(cardMap.cardMap.todo)
+ let todos = cardMap.cardMap.TODO.map{ Card(id: $0.id, title: $0.title, contents: $0.contents, boardName: $0.boardName) }
+ // TODO:- board의 이름에 따라 type값이 달라져야 한다
+ self.persistenceProvider?.insertBoard(type: .todo, cards: todos)
+ self.fetchResultInBoard[board] = Result.success(todos)
case .failure(let error):
-
Log.error(error)
+ self.fetchResultInBoard[board] = Result.success(resultFromCoredata)
}
}
}
}
- func getCards(in board: TodoBoard) -> Result<[CardData], DataTaskError> {
+ func deleteCard(id cardId: Int, at boardType: TodoBoard) {
+ dataTask?.requestDelete(parameter: cardId) { [weak self] result in
+
+ guard let id = try? result.get(), var fetchedResult = try? self?.fetchResultInBoard[boardType]?.get() else {
+ return
+ }
+
+ fetchedResult.removeAll(where: {data in data.id == id})
+ self?.fetchResultInBoard[boardType] = Result.success(fetchedResult)
+ }
+ }
+
+ func getCards(in board: TodoBoard) -> Result<[Card], DataTaskError> {
guard fetchResultInBoard.keys.contains(board), let result = fetchResultInBoard[board] else {
return Result.failure(DataTaskError.notConnect)
}
-
return result
}
}
diff --git a/Client/iOS/TodoList/SceneDelegate.swift b/Client/iOS/TodoList/SceneDelegate.swift
index cf626ea15..fc9481b48 100644
--- a/Client/iOS/TodoList/SceneDelegate.swift
+++ b/Client/iOS/TodoList/SceneDelegate.swift
@@ -13,9 +13,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
- // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
- // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
- // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
diff --git a/Client/iOS/TodoList/View/TodoRepositoryRespondWrapper.swift b/Client/iOS/TodoList/View/TodoRepositoryRespondWrapper.swift
index b57e647f4..1eaf7845c 100644
--- a/Client/iOS/TodoList/View/TodoRepositoryRespondWrapper.swift
+++ b/Client/iOS/TodoList/View/TodoRepositoryRespondWrapper.swift
@@ -9,7 +9,7 @@ class TodoRepositoryRespondWrapper: NSObject {
var todoTableView: TodoTableView
var todoBoard: TodoBoard
- private(set) var dataSource = [CardData]()
+ private(set) var dataSource = [Card]()
var badgeDelegate: TodoBadgeDelegate?
init(_ tableView: TodoTableView, in board: TodoBoard) {
@@ -28,7 +28,7 @@ class TodoRepositoryRespondWrapper: NSObject {
guard
let info = noti.userInfo,
- let result = info["result"] as? Result<[CardData], DataTaskError>
+ let result = info["result"] as? Result<[Card], DataTaskError>
else {
return
}
@@ -51,13 +51,13 @@ class TodoRepositoryRespondWrapper: NSObject {
return (0.. Int {
- dataSource.count
+ let result = (dataSource.count * 2) - 1
+ return result < 0 ? 0 : result
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+
+ if 0 < indexPath.row, indexPath.row.isMultiple(of: 2) == false {
+ let cell = UITableViewCell()
+ cell.heightAnchor.constraint(equalToConstant: 16).isActive = true
+ cell.contentView.backgroundColor = UIColor(named: "gray6")
+ return cell
+ }
+
guard let cell = tableView.dequeueReusableCell(withIdentifier: TodoTableViewCell.cellName, for: indexPath) as? TodoTableViewCell else {
return UITableViewCell()
}
- cell.applyTextAllLabels(data: dataSource[indexPath.row])
-
+ cell.applyTextAllLabels(data: dataSource[indexPath.row / 2])
+ cell.isUserInteractionEnabled = true
return cell
}
}
-extension TodoRepositoryRespondWrapper: UITableViewDelegate { }
+extension TodoRepositoryRespondWrapper: UITableViewDelegate {
+
+ func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
+
+ if let cell = tableView.cellForRow(at: indexPath) as? TodoTableViewCell {
+ cell.roundedView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMinXMinYCorner]
+ }
+
+ let action = UIContextualAction(
+ style: .destructive,
+ title: "Delete")
+ { [weak self] action, view, completion in
+
+ guard let self = self else { return }
+
+ AppDelegate.middleWare.deleteCard(id: self.dataSource[indexPath.row/2].id, at: self.todoBoard)
+ completion(true)
+ action.backgroundColor = .red
+ }
+
+ return UISwipeActionsConfiguration(actions: [action])
+ }
+
+ func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
+ if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) as? TodoTableViewCell {
+ cell.roundedView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMinXMinYCorner, .layerMaxXMaxYCorner, .layerMaxXMinYCorner]
+ }
+ }
+}
diff --git a/Client/iOS/TodoList/ViewControllers/ViewController.swift b/Client/iOS/TodoList/ViewControllers/ViewController.swift
index 0a96c2d0c..846ff92e1 100644
--- a/Client/iOS/TodoList/ViewControllers/ViewController.swift
+++ b/Client/iOS/TodoList/ViewControllers/ViewController.swift
@@ -6,6 +6,7 @@ protocol TodoEndPointViewController {
}
class ViewController: UIViewController {
+
override func viewDidLoad() {
super.viewDidLoad()
}