From 7de4e2b064b15119a295c8d4712fb79ab9dbf33f Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 22 Sep 2023 00:43:07 +0900 Subject: [PATCH 01/25] =?UTF-8?q?feat:=20tableView=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager/MainViewController.swift | 132 +++++++++++++++++- 1 file changed, 129 insertions(+), 3 deletions(-) diff --git a/ProjectManager/ProjectManager/MainViewController.swift b/ProjectManager/ProjectManager/MainViewController.swift index 6cd86ef55..400352678 100644 --- a/ProjectManager/ProjectManager/MainViewController.swift +++ b/ProjectManager/ProjectManager/MainViewController.swift @@ -6,10 +6,136 @@ import UIKit -class MainViewController: UIViewController { - +final class MainViewController: UIViewController { + private let todoTableView: UITableView = { + let tableView = UITableView() + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.backgroundColor = .systemGray5 + + return tableView + }() + + private let doingTableView: UITableView = { + let tableView = UITableView() + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.backgroundColor = .systemGray5 + + return tableView + }() + + private let doneTableView: UITableView = { + let tableView = UITableView() + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.backgroundColor = .systemGray5 + + return tableView + }() + + private var tableViewData: [UITableView: [Int: Int]] = [:] + override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = .red + + setUpViewController() + configureUI() + setUpTableViewLayout() + setUpTableView() + } + + private func setUpViewController() { + view.backgroundColor = .systemBackground + title = "Project Manager" + } + + private func configureUI() { + view.addSubview(todoTableView) + view.addSubview(doingTableView) + view.addSubview(doneTableView) + } + + private func setUpTableViewLayout() { + let tableViewWidth = view.bounds.width / 3.0 + + NSLayoutConstraint.activate([ + todoTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + todoTableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + todoTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), + todoTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + + doingTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + doingTableView.leadingAnchor.constraint(equalTo: todoTableView.trailingAnchor), + doingTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), + doingTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + + doneTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + doneTableView.leadingAnchor.constraint(equalTo: doingTableView.trailingAnchor), + doneTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), + doneTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + doneTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } + + private func setUpTableView() { + todoTableView.dataSource = self + todoTableView.delegate = self + todoTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + tableViewData[todoTableView] = [0:1, 1:2] + + doingTableView.dataSource = self + doingTableView.delegate = self + doingTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + tableViewData[doingTableView] = [0:1, 1:2] + + doneTableView.dataSource = self + doneTableView.delegate = self + doneTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + tableViewData[doneTableView] = [0:1, 1:2] + } +} + +extension MainViewController: UITableViewDataSource { + func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if let rowInSection = tableViewData[tableView]?[section] { + return rowInSection + } + + return 0 } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) + + switch (tableView, indexPath.section) { + case (todoTableView, 0): + cell.textLabel?.text = "TODO" + cell.backgroundColor = .systemGray5 + case (todoTableView, 1): + cell.textLabel?.text = "1" + + case (doingTableView, 0): + cell.textLabel?.text = "Doing" + cell.backgroundColor = .systemGray5 + case (doingTableView, 1): + cell.textLabel?.text = "2" + + case (doneTableView, 0): + cell.textLabel?.text = "Done" + cell.backgroundColor = .systemGray5 + case (doneTableView, 1): + cell.textLabel?.text = "3" + + default: + break + } + + return cell + } +} + +extension MainViewController: UITableViewDelegate { + } From af73086e8f24ba1d08aee431c7cc4d352d288142 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Tue, 26 Sep 2023 20:43:51 +0900 Subject: [PATCH 02/25] =?UTF-8?q?feat:=20=ED=8C=8C=EC=9D=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=EB=B0=8F,=20=EC=A0=9C=EB=AA=A9,=EB=82=B4=EC=9A=A9?= =?UTF-8?q?=20=EC=85=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => App}/AppDelegate.swift | 0 .../{ => App}/SceneDelegate.swift | 0 .../{ => Controller}/MainViewController.swift | 0 .../Base.lproj/LaunchScreen.storyboard | 18 +++-- .../ProjectManager/View/DescriptionCell.swift | 79 +++++++++++++++++++ .../ProjectManager/View/ListTitleCell.swift | 64 +++++++++++++++ 6 files changed, 156 insertions(+), 5 deletions(-) rename ProjectManager/ProjectManager/{ => App}/AppDelegate.swift (100%) rename ProjectManager/ProjectManager/{ => App}/SceneDelegate.swift (100%) rename ProjectManager/ProjectManager/{ => Controller}/MainViewController.swift (100%) rename ProjectManager/ProjectManager/{ => View}/Base.lproj/LaunchScreen.storyboard (57%) create mode 100644 ProjectManager/ProjectManager/View/DescriptionCell.swift create mode 100644 ProjectManager/ProjectManager/View/ListTitleCell.swift diff --git a/ProjectManager/ProjectManager/AppDelegate.swift b/ProjectManager/ProjectManager/App/AppDelegate.swift similarity index 100% rename from ProjectManager/ProjectManager/AppDelegate.swift rename to ProjectManager/ProjectManager/App/AppDelegate.swift diff --git a/ProjectManager/ProjectManager/SceneDelegate.swift b/ProjectManager/ProjectManager/App/SceneDelegate.swift similarity index 100% rename from ProjectManager/ProjectManager/SceneDelegate.swift rename to ProjectManager/ProjectManager/App/SceneDelegate.swift diff --git a/ProjectManager/ProjectManager/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift similarity index 100% rename from ProjectManager/ProjectManager/MainViewController.swift rename to ProjectManager/ProjectManager/Controller/MainViewController.swift diff --git a/ProjectManager/ProjectManager/Base.lproj/LaunchScreen.storyboard b/ProjectManager/ProjectManager/View/Base.lproj/LaunchScreen.storyboard similarity index 57% rename from ProjectManager/ProjectManager/Base.lproj/LaunchScreen.storyboard rename to ProjectManager/ProjectManager/View/Base.lproj/LaunchScreen.storyboard index 865e9329f..17f10a541 100644 --- a/ProjectManager/ProjectManager/Base.lproj/LaunchScreen.storyboard +++ b/ProjectManager/ProjectManager/View/Base.lproj/LaunchScreen.storyboard @@ -1,8 +1,11 @@ - - + + + - + + + @@ -11,10 +14,10 @@ - + - + @@ -22,4 +25,9 @@ + + + + + diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift new file mode 100644 index 000000000..459b5e4cd --- /dev/null +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -0,0 +1,79 @@ +// +// DescriptionCell.swift +// ProjectManager +// +// Created by 1 on 2023/09/26. +// + +import UIKit + +final class DescriptionCell: UITableViewCell { + private let titleLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .title1) + label.translatesAutoresizingMaskIntoConstraints = false + + return label + }() + + private let bodyLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .body) + label.translatesAutoresizingMaskIntoConstraints = false + + return label + }() + + private let dateLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .callout) + label.translatesAutoresizingMaskIntoConstraints = false + + return label + }() + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + setUpLabel() + configureUI() + + } + + override func prepareForReuse() { + titleLabel.text = nil + bodyLabel.text = nil + dateLabel.text = nil + } + + private func setUpLabel() { + contentView.addSubview(titleLabel) + contentView.addSubview(bodyLabel) + contentView.addSubview(dateLabel) + } + + private func configureUI() { + accessoryType = .disclosureIndicator + + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), + titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + + bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4), + bodyLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + + dateLabel.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 4), + dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4) + ]) + } + + func setModel(title: String, body: String, date: String) { + titleLabel.text = title + bodyLabel.text = body + dateLabel.text = date + } +} diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift new file mode 100644 index 000000000..ebe11b89e --- /dev/null +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -0,0 +1,64 @@ +// +// ListTitleCell.swift +// ProjectManager +// +// Created by 1 on 2023/09/25. +// + +import UIKit + +final class ListTitleCell: UITableViewCell { + private let titleLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .title1) + label.translatesAutoresizingMaskIntoConstraints = false + + return label + }() + + private let countLabel: UILabel = { + let label = UILabel() + label.font = .preferredFont(forTextStyle: .callout) + label.translatesAutoresizingMaskIntoConstraints = false + + return label + }() + + override func awakeFromNib() { + super.awakeFromNib() + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + setUpLabel() + configureUI() + } + + override func prepareForReuse() { + titleLabel.text = nil + countLabel.text = nil + } + + private func setUpLabel() { + contentView.addSubview(titleLabel) + contentView.addSubview(countLabel) + } + + private func configureUI() { + accessoryType = .disclosureIndicator + + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), + titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 4), + + countLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4), + countLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor) + ]) + } + + func setModel(title: String, count: Int) { + titleLabel.text = title + countLabel.text = String(count) + } +} From 68c6381e8d19861de6d3b7cc7bd77535754e5ac8 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Tue, 26 Sep 2023 20:44:05 +0900 Subject: [PATCH 03/25] =?UTF-8?q?feat:=20=EC=8A=A4=ED=83=9D=EB=B7=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1(=ED=85=8C=EC=9D=B4=EB=B8=94=EB=B7=B0=20?= =?UTF-8?q?=EB=84=A3=EA=B8=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 42 +++++++- .../Controller/MainViewController.swift | 97 ++++++++++++------- 2 files changed, 99 insertions(+), 40 deletions(-) diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 4622d4d6c..6d6b8e0c8 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */; }; + 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -15,6 +17,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTitleCell.swift; sourceTree = ""; }; + 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCell.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -35,6 +39,33 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 63C5ECB22AC1944F003904C4 /* App */ = { + isa = PBXGroup; + children = ( + C7431F0525F51E1D0094C4CF /* AppDelegate.swift */, + C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */, + ); + path = App; + sourceTree = ""; + }; + 63C5ECB32AC19459003904C4 /* Controller */ = { + isa = PBXGroup; + children = ( + C7431F0925F51E1D0094C4CF /* MainViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + 63C5ECB42AC19464003904C4 /* View */ = { + isa = PBXGroup; + children = ( + C7431F1025F51E1E0094C4CF /* LaunchScreen.storyboard */, + 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */, + 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */, + ); + path = View; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -54,12 +85,11 @@ C7431F0425F51E1D0094C4CF /* ProjectManager */ = { isa = PBXGroup; children = ( - C7431F0525F51E1D0094C4CF /* AppDelegate.swift */, - C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */, - C7431F0925F51E1D0094C4CF /* MainViewController.swift */, - C7431F0E25F51E1E0094C4CF /* Assets.xcassets */, - C7431F1025F51E1E0094C4CF /* LaunchScreen.storyboard */, + 63C5ECB22AC1944F003904C4 /* App */, + 63C5ECB32AC19459003904C4 /* Controller */, + 63C5ECB42AC19464003904C4 /* View */, C7431F1325F51E1E0094C4CF /* Info.plist */, + C7431F0E25F51E1E0094C4CF /* Assets.xcassets */, ); path = ProjectManager; sourceTree = ""; @@ -134,8 +164,10 @@ buildActionMask = 2147483647; files = ( C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, + 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, + 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 400352678..4adefc847 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -30,6 +30,18 @@ final class MainViewController: UIViewController { return tableView }() + + private let stackView: UIStackView = { + let stackView = UIStackView() + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.axis = .horizontal + stackView.alignment = .fill + stackView.distribution = .fillEqually + stackView.spacing = 12 + stackView.backgroundColor = .systemGray5 + + return stackView + }() private var tableViewData: [UITableView: [Int: Int]] = [:] @@ -48,47 +60,45 @@ final class MainViewController: UIViewController { } private func configureUI() { - view.addSubview(todoTableView) - view.addSubview(doingTableView) - view.addSubview(doneTableView) + stackView.addArrangedSubview(todoTableView) + stackView.addArrangedSubview(doingTableView) + stackView.addArrangedSubview(doneTableView) + + view.addSubview(stackView) } private func setUpTableViewLayout() { let tableViewWidth = view.bounds.width / 3.0 NSLayoutConstraint.activate([ - todoTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - todoTableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), - todoTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), - todoTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), - - doingTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - doingTableView.leadingAnchor.constraint(equalTo: todoTableView.trailingAnchor), - doingTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), - doingTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), - - doneTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - doneTableView.leadingAnchor.constraint(equalTo: doingTableView.trailingAnchor), - doneTableView.widthAnchor.constraint(equalToConstant: tableViewWidth), - doneTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - doneTableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) + + todoTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true + doingTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true + doneTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true } private func setUpTableView() { todoTableView.dataSource = self todoTableView.delegate = self - todoTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + todoTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") + todoTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") tableViewData[todoTableView] = [0:1, 1:2] doingTableView.dataSource = self doingTableView.delegate = self - doingTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + doingTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") + doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") tableViewData[doingTableView] = [0:1, 1:2] doneTableView.dataSource = self doneTableView.delegate = self - doneTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") + doneTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") + doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") tableViewData[doneTableView] = [0:1, 1:2] } } @@ -107,32 +117,49 @@ extension MainViewController: UITableViewDataSource { } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) - switch (tableView, indexPath.section) { case (todoTableView, 0): - cell.textLabel?.text = "TODO" - cell.backgroundColor = .systemGray5 + guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + + listCell.setModel(title: "TODO", count: 1) + listCell.backgroundColor = .systemGray5 + return listCell + case (todoTableView, 1): - cell.textLabel?.text = "1" + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + + descriptionCell.setModel(title: "제목", body: "내용", date: "날짜") + return descriptionCell case (doingTableView, 0): - cell.textLabel?.text = "Doing" - cell.backgroundColor = .systemGray5 + guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + + listCell.setModel(title: "DOING", count: 2) + listCell.backgroundColor = .systemGray5 + return listCell + case (doingTableView, 1): - cell.textLabel?.text = "2" + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + + descriptionCell.setModel(title: "제목1", body: "내용1", date: "날짜1") + return descriptionCell case (doneTableView, 0): - cell.textLabel?.text = "Done" - cell.backgroundColor = .systemGray5 + guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + + listCell.setModel(title: "DONE", count: 3) + listCell.backgroundColor = .systemGray5 + return listCell + case (doneTableView, 1): - cell.textLabel?.text = "3" + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + descriptionCell.setModel(title: "제목2", body: "내용2", date: "날짜2") + return descriptionCell + default: - break + return UITableViewCell() } - - return cell } } From 647d89ef59e532b1ffe67b54b11319e46e86db76 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Tue, 26 Sep 2023 20:45:25 +0900 Subject: [PATCH 04/25] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager/Controller/MainViewController.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 4adefc847..4461fc77d 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -68,18 +68,12 @@ final class MainViewController: UIViewController { } private func setUpTableViewLayout() { - let tableViewWidth = view.bounds.width / 3.0 - NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) - - todoTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true - doingTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true - doneTableView.widthAnchor.constraint(equalToConstant: tableViewWidth).isActive = true } private func setUpTableView() { From 9acef1b36c0c0800ece6c24f99fce534479302fb Mon Sep 17 00:00:00 2001 From: hemg2 Date: Tue, 26 Sep 2023 21:20:26 +0900 Subject: [PATCH 05/25] =?UTF-8?q?feat:=20=ED=8C=9D=EC=97=85=EB=B7=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 4 ++ .../Controller/AddTODOViewController.swift | 39 +++++++++++++++++++ .../Controller/MainViewController.swift | 20 +++++++++- .../ProjectManager/View/DescriptionCell.swift | 10 ++--- .../ProjectManager/View/ListTitleCell.swift | 8 ++-- 5 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 ProjectManager/ProjectManager/Controller/AddTODOViewController.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 6d6b8e0c8..911f0dcf2 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */; }; 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */; }; + 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -19,6 +20,7 @@ /* Begin PBXFileReference section */ 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTitleCell.swift; sourceTree = ""; }; 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCell.swift; sourceTree = ""; }; + 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTODOViewController.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -52,6 +54,7 @@ isa = PBXGroup; children = ( C7431F0925F51E1D0094C4CF /* MainViewController.swift */, + 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */, ); path = Controller; sourceTree = ""; @@ -165,6 +168,7 @@ files = ( C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, + 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift new file mode 100644 index 000000000..bfdd0b757 --- /dev/null +++ b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift @@ -0,0 +1,39 @@ +// +// AddTODOViewController.swift +// ProjectManager +// +// Created by 1 on 2023/09/26. +// + +import UIKit + +final class AddTODOViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + setUpViewController() + setUpBarButtonItem() + } + + private func setUpViewController() { + view.backgroundColor = .systemBackground + title = "TODO" + } + + private func setUpBarButtonItem() { + let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneButton)) + navigationItem.rightBarButtonItem = doneButton + + let cancel = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(cancelButton)) + navigationItem.leftBarButtonItem = cancel + } + + @objc private func doneButton() { + dismiss(animated: true) + } + + @objc private func cancelButton() { + dismiss(animated: true) + } +} diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 4461fc77d..b67883019 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -30,7 +30,7 @@ final class MainViewController: UIViewController { return tableView }() - + private let stackView: UIStackView = { let stackView = UIStackView() stackView.translatesAutoresizingMaskIntoConstraints = false @@ -49,6 +49,7 @@ final class MainViewController: UIViewController { super.viewDidLoad() setUpViewController() + setUpBarButtonItem() configureUI() setUpTableViewLayout() setUpTableView() @@ -66,6 +67,21 @@ final class MainViewController: UIViewController { view.addSubview(stackView) } + + private func setUpBarButtonItem() { + let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addButton)) + navigationItem.rightBarButtonItem = addButton + } + + @objc private func addButton() { + let addTODOView = AddTODOViewController() + let navigationController = UINavigationController(rootViewController: addTODOView) + let backgroundView = UIView(frame: view.bounds) + backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) + addTODOView.view.sendSubviewToBack(backgroundView) + + present(navigationController, animated: true) + } private func setUpTableViewLayout() { NSLayoutConstraint.activate([ @@ -150,7 +166,7 @@ extension MainViewController: UITableViewDataSource { descriptionCell.setModel(title: "제목2", body: "내용2", date: "날짜2") return descriptionCell - + default: return UITableViewCell() } diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift index 459b5e4cd..5cc74d736 100644 --- a/ProjectManager/ProjectManager/View/DescriptionCell.swift +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -31,18 +31,18 @@ final class DescriptionCell: UITableViewCell { return label }() - + override func awakeFromNib() { super.awakeFromNib() } - + override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) setUpLabel() configureUI() } - + override func prepareForReuse() { titleLabel.text = nil bodyLabel.text = nil @@ -56,8 +56,6 @@ final class DescriptionCell: UITableViewCell { } private func configureUI() { - accessoryType = .disclosureIndicator - NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), @@ -70,7 +68,7 @@ final class DescriptionCell: UITableViewCell { dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4) ]) } - + func setModel(title: String, body: String, date: String) { titleLabel.text = title bodyLabel.text = body diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift index ebe11b89e..3c8a7e65c 100644 --- a/ProjectManager/ProjectManager/View/ListTitleCell.swift +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -23,11 +23,11 @@ final class ListTitleCell: UITableViewCell { return label }() - + override func awakeFromNib() { super.awakeFromNib() } - + override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) setUpLabel() @@ -45,8 +45,6 @@ final class ListTitleCell: UITableViewCell { } private func configureUI() { - accessoryType = .disclosureIndicator - NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), @@ -56,7 +54,7 @@ final class ListTitleCell: UITableViewCell { countLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor) ]) } - + func setModel(title: String, count: Int) { titleLabel.text = title countLabel.text = String(count) From 3fb04ce897b41c64188829f622759186ad781f0c Mon Sep 17 00:00:00 2001 From: hemg2 Date: Wed, 27 Sep 2023 22:32:51 +0900 Subject: [PATCH 06/25] =?UTF-8?q?feat:=20AddTODOViewController=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 24 ++++++ .../Controller/AddTODOViewController.swift | 83 ++++++++++++++++++- .../ProjectManager/View/DescriptionCell.swift | 5 +- .../ProjectManager/View/ListTitleCell.swift | 3 +- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 911f0dcf2..14e187046 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -69,6 +69,29 @@ path = View; sourceTree = ""; }; + 63C5ECBB2AC45243003904C4 /* Model */ = { + isa = PBXGroup; + children = ( + 63C5ECBF2AC465BD003904C4 /* CoreDataManager */, + 63C5ECBE2AC45277003904C4 /* Entity */, + ); + path = Model; + sourceTree = ""; + }; + 63C5ECBE2AC45277003904C4 /* Entity */ = { + isa = PBXGroup; + children = ( + ); + path = Entity; + sourceTree = ""; + }; + 63C5ECBF2AC465BD003904C4 /* CoreDataManager */ = { + isa = PBXGroup; + children = ( + ); + path = CoreDataManager; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -88,6 +111,7 @@ C7431F0425F51E1D0094C4CF /* ProjectManager */ = { isa = PBXGroup; children = ( + 63C5ECBB2AC45243003904C4 /* Model */, 63C5ECB22AC1944F003904C4 /* App */, 63C5ECB32AC19459003904C4 /* Controller */, 63C5ECB42AC19464003904C4 /* View */, diff --git a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift index bfdd0b757..2010f4286 100644 --- a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift +++ b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift @@ -2,23 +2,57 @@ // AddTODOViewController.swift // ProjectManager // -// Created by 1 on 2023/09/26. +// Created by Hemg on 2023/09/26. // import UIKit final class AddTODOViewController: UIViewController { + private let titleTextField: UITextField = { + let textField = UITextField() + textField.translatesAutoresizingMaskIntoConstraints = false + textField.font = .preferredFont(forTextStyle: .title1) + textField.placeholder = "Title" + textField.layer.borderColor = UIColor.lightGray.cgColor + textField.layer.borderWidth = 1.0 + + return textField + }() + + private let bodyTextView: UITextView = { + let textView = UITextView() + textView.translatesAutoresizingMaskIntoConstraints = false + textView.font = .preferredFont(forTextStyle: .body) + textView.text = "여기는 할일 내용 입력하는 곳입니다." + textView.textColor = .placeholderText + textView.layer.borderColor = UIColor.lightGray.cgColor + textView.layer.borderWidth = 1.0 + + return textView + }() + + private let datePicker: UIDatePicker = { + let datePicker = UIDatePicker() + datePicker.translatesAutoresizingMaskIntoConstraints = false + datePicker.preferredDatePickerStyle = .wheels + datePicker.datePickerMode = .date + + return datePicker + }() override func viewDidLoad() { super.viewDidLoad() setUpViewController() setUpBarButtonItem() + configureUI() + setUpViewLayout() } private func setUpViewController() { view.backgroundColor = .systemBackground title = "TODO" + bodyTextView.delegate = self } private func setUpBarButtonItem() { @@ -36,4 +70,51 @@ final class AddTODOViewController: UIViewController { @objc private func cancelButton() { dismiss(animated: true) } + + private func configureUI() { + view.addSubview(titleTextField) + view.addSubview(bodyTextView) + view.addSubview(datePicker) + } + + private func setUpViewLayout() { + NSLayoutConstraint.activate([ + titleTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + titleTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 4), + titleTextField.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -4), + + datePicker.topAnchor.constraint(equalTo: titleTextField.bottomAnchor, constant: 4), + datePicker.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 4), + datePicker.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -4), + + bodyTextView.topAnchor.constraint(equalTo: datePicker.bottomAnchor, constant: 4), + bodyTextView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 4), + bodyTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -4), + bodyTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -4) + ]) + } +} + +extension AddTODOViewController: UITextViewDelegate { + func textViewDidBeginEditing(_ textView: UITextView) { + if textView.text == "여기는 할일 내용 입력하는 곳입니다." { + textView.text = "" + textView.textColor = .label + } + } + + func textViewDidEndEditing(_ textView: UITextView) { + if textView.text.isEmpty { + textView.text = "여기는 할일 내용 입력하는 곳입니다." + textView.textColor = .placeholderText + } + } + + func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + let currentText = textView.text ?? "" + guard let stringRange = Range(range, in: currentText) else { return false } + let changedText = currentText.replacingCharacters(in: stringRange, with: text) + + return changedText.count <= 999 + } } diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift index 5cc74d736..4edd44cee 100644 --- a/ProjectManager/ProjectManager/View/DescriptionCell.swift +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -2,7 +2,7 @@ // DescriptionCell.swift // ProjectManager // -// Created by 1 on 2023/09/26. +// Created by Hemg on 2023/09/26. // import UIKit @@ -59,12 +59,15 @@ final class DescriptionCell: UITableViewCell { NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -4), bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4), bodyLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + bodyLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -4), dateLabel.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 4), dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + dateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -4), dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4) ]) } diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift index 3c8a7e65c..b1d7a4db5 100644 --- a/ProjectManager/ProjectManager/View/ListTitleCell.swift +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -2,7 +2,7 @@ // ListTitleCell.swift // ProjectManager // -// Created by 1 on 2023/09/25. +// Created by Hemg on 2023/09/25. // import UIKit @@ -48,6 +48,7 @@ final class ListTitleCell: UITableViewCell { NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -4), titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 4), countLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4), From 4c34572be86073a25ec05683901a5a95f6407c18 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Wed, 27 Sep 2023 22:58:58 +0900 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20CoreData=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 29 ++++++++ .../CoreDataManager/CoreDataManager.swift | 66 +++++++++++++++++++ .../CoreDataManager/TODO+CoreDataClass.swift | 12 ++++ .../TODO+CoreDataProperties.swift | 23 +++++++ .../TODO.xcdatamodel/contents | 9 +++ 5 files changed, 139 insertions(+) create mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift create mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift create mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift create mode 100644 ProjectManager/ProjectManager/TODO.xcdatamodeld/TODO.xcdatamodel/contents diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 14e187046..6f78b1f31 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -10,6 +10,10 @@ 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */; }; 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */; }; 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */; }; + 63C5ECC12AC466FB003904C4 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */; }; + 63C5ECC42AC46751003904C4 /* TODO.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */; }; + 63C5ECC72AC467AF003904C4 /* TODO+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */; }; + 63C5ECC82AC467AF003904C4 /* TODO+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -21,6 +25,10 @@ 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTitleCell.swift; sourceTree = ""; }; 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCell.swift; sourceTree = ""; }; 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTODOViewController.swift; sourceTree = ""; }; + 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; + 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TODO.xcdatamodel; sourceTree = ""; }; + 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataClass.swift"; sourceTree = ""; }; + 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataProperties.swift"; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -88,6 +96,9 @@ 63C5ECBF2AC465BD003904C4 /* CoreDataManager */ = { isa = PBXGroup; children = ( + 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */, + 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */, + 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */, ); path = CoreDataManager; sourceTree = ""; @@ -117,6 +128,7 @@ 63C5ECB42AC19464003904C4 /* View */, C7431F1325F51E1E0094C4CF /* Info.plist */, C7431F0E25F51E1E0094C4CF /* Assets.xcassets */, + 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */, ); path = ProjectManager; sourceTree = ""; @@ -195,7 +207,11 @@ 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, + 63C5ECC82AC467AF003904C4 /* TODO+CoreDataProperties.swift in Sources */, + 63C5ECC12AC466FB003904C4 /* CoreDataManager.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, + 63C5ECC42AC46751003904C4 /* TODO.xcdatamodeld in Sources */, + 63C5ECC72AC467AF003904C4 /* TODO+CoreDataClass.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -389,6 +405,19 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */, + ); + currentVersion = 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */; + path = TODO.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = C7431EFA25F51E1D0094C4CF /* Project object */; } diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift new file mode 100644 index 000000000..ba9d1b0f3 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift @@ -0,0 +1,66 @@ +// +// CoreDataManager.swift +// ProjectManager +// +// Created by Hemg on 2023/09/27. +// + +import CoreData + +final class CoreDataManager { + private var todoList = [TODO]() + private var mainContext: NSManagedObjectContext { + return persistentContainer.viewContext + } + + func fetchTODO() -> [TODO] { + let request: NSFetchRequest = TODO.fetchRequest() + let sortByDate = NSSortDescriptor(key: "date", ascending: false) + request.sortDescriptors = [sortByDate] + + do { + let todos = try mainContext.fetch(request) + return todos + } catch { + fatalError() + } + } + + func createTODO() -> [TODO] { + let newTODO = TODO(context: mainContext) + newTODO.id = UUID() + newTODO.date = Date() + + return [newTODO] + } + + func deletTODO(_ todo: TODO?) { + guard let todo = todo else { + return + } + mainContext.delete(todo) + saveContext() + } + + lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "TODO") + container.loadPersistentStores(completionHandler: { (_, error) in + if let error = error as NSError? { + fatalError("Unresolved error \(error), \(error.userInfo)") + } + }) + return container + }() + + func saveContext () { + let context = persistentContainer.viewContext + if context.hasChanges { + do { + try context.save() + } catch { + let nsError = error as NSError + fatalError("Unresolved error \(nsError), \(nsError.userInfo)") + } + } + } +} diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift new file mode 100644 index 000000000..b55154770 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift @@ -0,0 +1,12 @@ +// +// TODO+CoreDataClass.swift +// ProjectManager +// +// Created by Hemg on 2023/09/27. +// +// + +import CoreData + +@objc(TODO) +public class TODO: NSManagedObject {} diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift new file mode 100644 index 000000000..47656b061 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift @@ -0,0 +1,23 @@ +// +// TODO+CoreDataProperties.swift +// ProjectManager +// +// Created by Hemg on 2023/09/27. +// +// + +import CoreData + +extension TODO { + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "TODO") + } + + @NSManaged public var title: String? + @NSManaged public var body: String? + @NSManaged public var date: Date? +} + +extension TODO : Identifiable { + @NSManaged public var id: UUID? +} diff --git a/ProjectManager/ProjectManager/TODO.xcdatamodeld/TODO.xcdatamodel/contents b/ProjectManager/ProjectManager/TODO.xcdatamodeld/TODO.xcdatamodel/contents new file mode 100644 index 000000000..08abb64ad --- /dev/null +++ b/ProjectManager/ProjectManager/TODO.xcdatamodeld/TODO.xcdatamodel/contents @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From 5cc83b098e343e865436fa11eff8c85d1255aec8 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Thu, 28 Sep 2023 01:03:33 +0900 Subject: [PATCH 08/25] =?UTF-8?q?feat:=20Model=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 18 ++++++++++++++- .../Model/DataManager/DataManager.swift | 23 +++++++++++++++++++ .../Model/Entity/ProjectManager.swift | 14 +++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ProjectManager/ProjectManager/Model/DataManager/DataManager.swift create mode 100644 ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 6f78b1f31..2eb54f7de 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 63C5ECC42AC46751003904C4 /* TODO.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */; }; 63C5ECC72AC467AF003904C4 /* TODO+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */; }; 63C5ECC82AC467AF003904C4 /* TODO+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */; }; + 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; + 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -29,6 +31,8 @@ 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TODO.xcdatamodel; sourceTree = ""; }; 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataClass.swift"; sourceTree = ""; }; 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataProperties.swift"; sourceTree = ""; }; + 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; + 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -80,8 +84,9 @@ 63C5ECBB2AC45243003904C4 /* Model */ = { isa = PBXGroup; children = ( - 63C5ECBF2AC465BD003904C4 /* CoreDataManager */, + 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, + 63C5ECBF2AC465BD003904C4 /* CoreDataManager */, ); path = Model; sourceTree = ""; @@ -89,6 +94,7 @@ 63C5ECBE2AC45277003904C4 /* Entity */ = { isa = PBXGroup; children = ( + 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */, ); path = Entity; sourceTree = ""; @@ -103,6 +109,14 @@ path = CoreDataManager; sourceTree = ""; }; + 63C5ECCB2AC46F4E003904C4 /* DataManager */ = { + isa = PBXGroup; + children = ( + 63C5ECCC2AC46F83003904C4 /* DataManager.swift */, + ); + path = DataManager; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -202,6 +216,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, + 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift new file mode 100644 index 000000000..ad4536cc6 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift @@ -0,0 +1,23 @@ +// +// DataManager.swift +// ProjectManager +// +// Created by Hemg on 2023/09/27. +// + +import Foundation + +final class DataManager { + static let shared = DataManager() + private var todoItems = [ProjectManager]() + private init() {} + + func addTodoItem(title: String, body: String, date: Date) { + let newItem = ProjectManager(title: title, body: body, date: date) + todoItems.append(newItem) + } + + func leadTodoItem() -> [ProjectManager] { + return todoItems + } +} diff --git a/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift b/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift new file mode 100644 index 000000000..2c08fab35 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift @@ -0,0 +1,14 @@ +// +// ProjectManager.swift +// ProjectManager +// +// Created by Hemg on 2023/09/27. +// + +import Foundation + +struct ProjectManager { + let title: String + let body: String + let date: Date +} From 0283d80bce59ec4e4283fa0bc6c539ce790590e3 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Thu, 28 Sep 2023 01:04:39 +0900 Subject: [PATCH 09/25] =?UTF-8?q?feat:=20=EB=8D=B8=EB=A6=AC=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=ED=8C=A8=ED=84=B4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/AddTODOViewController.swift | 17 ++++++++ .../Controller/MainViewController.swift | 40 +++++++++++++++---- .../ProjectManager/View/DescriptionCell.swift | 8 +++- .../ProjectManager/View/ListTitleCell.swift | 1 - 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift index 2010f4286..e01d81e6c 100644 --- a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift +++ b/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift @@ -7,6 +7,10 @@ import UIKit +protocol AddTodoDelegate: AnyObject { + func didAddTodoItem(title: String, body: String, date: Date) +} + final class AddTODOViewController: UIViewController { private let titleTextField: UITextField = { let textField = UITextField() @@ -39,6 +43,8 @@ final class AddTODOViewController: UIViewController { return datePicker }() + + weak var delegate: AddTodoDelegate? override func viewDidLoad() { super.viewDidLoad() @@ -64,6 +70,7 @@ final class AddTODOViewController: UIViewController { } @objc private func doneButton() { + setUpItemText() dismiss(animated: true) } @@ -93,6 +100,16 @@ final class AddTODOViewController: UIViewController { bodyTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -4) ]) } + + private func setUpItemText() { + let date = datePicker.date + guard let titleText = titleTextField.text, + let bodyText = bodyTextView.text else { + return + } + + delegate?.didAddTodoItem(title: titleText, body: bodyText, date: date) + } } extension AddTODOViewController: UITextViewDelegate { diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index b67883019..b9f1e609a 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -44,6 +44,7 @@ final class MainViewController: UIViewController { }() private var tableViewData: [UITableView: [Int: Int]] = [:] + private var todoItems = [ProjectManager]() override func viewDidLoad() { super.viewDidLoad() @@ -79,6 +80,7 @@ final class MainViewController: UIViewController { let backgroundView = UIView(frame: view.bounds) backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) addTODOView.view.sendSubviewToBack(backgroundView) + addTODOView.delegate = self present(navigationController, animated: true) } @@ -119,11 +121,26 @@ extension MainViewController: UITableViewDataSource { } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if let rowInSection = tableViewData[tableView]?[section] { - return rowInSection - } + switch (tableView, section) { + case (todoTableView, 0): + return 1 - return 0 + case (todoTableView, 1): + return todoItems.count + + case (doingTableView, 0): + return 1 + case (doingTableView, 1): + return 2 + + case (doneTableView, 0): + return 1 + case (doneTableView, 1): + return 2 + + default: + return 0 + } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -131,14 +148,15 @@ extension MainViewController: UITableViewDataSource { case (todoTableView, 0): guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } - listCell.setModel(title: "TODO", count: 1) + listCell.setModel(title: "TODO", count: todoItems.count) listCell.backgroundColor = .systemGray5 return listCell case (todoTableView, 1): guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } - descriptionCell.setModel(title: "제목", body: "내용", date: "날짜") + let todoItem = todoItems[indexPath.row] + descriptionCell.setModel(title: todoItem.title, body: todoItem.body, date: todoItem.date) return descriptionCell case (doingTableView, 0): @@ -151,7 +169,6 @@ extension MainViewController: UITableViewDataSource { case (doingTableView, 1): guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } - descriptionCell.setModel(title: "제목1", body: "내용1", date: "날짜1") return descriptionCell case (doneTableView, 0): @@ -164,7 +181,6 @@ extension MainViewController: UITableViewDataSource { case (doneTableView, 1): guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } - descriptionCell.setModel(title: "제목2", body: "내용2", date: "날짜2") return descriptionCell default: @@ -176,3 +192,11 @@ extension MainViewController: UITableViewDataSource { extension MainViewController: UITableViewDelegate { } + +extension MainViewController: AddTodoDelegate { + func didAddTodoItem(title: String, body: String, date: Date) { + DataManager.shared.addTodoItem(title: title, body: body, date: date) + todoItems = DataManager.shared.leadTodoItem() + todoTableView.reloadData() + } +} diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift index 4edd44cee..790512d1d 100644 --- a/ProjectManager/ProjectManager/View/DescriptionCell.swift +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -72,9 +72,13 @@ final class DescriptionCell: UITableViewCell { ]) } - func setModel(title: String, body: String, date: String) { + func setModel(title: String, body: String, date: Date) { titleLabel.text = title bodyLabel.text = body - dateLabel.text = date + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + let dateString = dateFormatter.string(from: date) + dateLabel.text = dateString } } diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift index b1d7a4db5..b59ba30ab 100644 --- a/ProjectManager/ProjectManager/View/ListTitleCell.swift +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -48,7 +48,6 @@ final class ListTitleCell: UITableViewCell { NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), - titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -4), titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 4), countLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4), From 0d02fd04714542d2ee7f7290c16306220ecca7fc Mon Sep 17 00:00:00 2001 From: hemg2 Date: Thu, 28 Sep 2023 15:25:43 +0900 Subject: [PATCH 10/25] =?UTF-8?q?refactor:=20Coredata=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 37 ----------- .../CoreDataManager/CoreDataManager.swift | 66 ------------------- .../CoreDataManager/TODO+CoreDataClass.swift | 12 ---- .../TODO+CoreDataProperties.swift | 23 ------- 4 files changed, 138 deletions(-) delete mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift delete mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift delete mode 100644 ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 2eb54f7de..0794753ca 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -10,10 +10,6 @@ 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */; }; 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */; }; 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */; }; - 63C5ECC12AC466FB003904C4 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */; }; - 63C5ECC42AC46751003904C4 /* TODO.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */; }; - 63C5ECC72AC467AF003904C4 /* TODO+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */; }; - 63C5ECC82AC467AF003904C4 /* TODO+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */; }; 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; @@ -27,10 +23,6 @@ 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTitleCell.swift; sourceTree = ""; }; 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCell.swift; sourceTree = ""; }; 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTODOViewController.swift; sourceTree = ""; }; - 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; - 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TODO.xcdatamodel; sourceTree = ""; }; - 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataClass.swift"; sourceTree = ""; }; - 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TODO+CoreDataProperties.swift"; sourceTree = ""; }; 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -86,7 +78,6 @@ children = ( 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, - 63C5ECBF2AC465BD003904C4 /* CoreDataManager */, ); path = Model; sourceTree = ""; @@ -99,16 +90,6 @@ path = Entity; sourceTree = ""; }; - 63C5ECBF2AC465BD003904C4 /* CoreDataManager */ = { - isa = PBXGroup; - children = ( - 63C5ECC52AC467AF003904C4 /* TODO+CoreDataClass.swift */, - 63C5ECC62AC467AF003904C4 /* TODO+CoreDataProperties.swift */, - 63C5ECC02AC466FB003904C4 /* CoreDataManager.swift */, - ); - path = CoreDataManager; - sourceTree = ""; - }; 63C5ECCB2AC46F4E003904C4 /* DataManager */ = { isa = PBXGroup; children = ( @@ -142,7 +123,6 @@ 63C5ECB42AC19464003904C4 /* View */, C7431F1325F51E1E0094C4CF /* Info.plist */, C7431F0E25F51E1E0094C4CF /* Assets.xcassets */, - 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */, ); path = ProjectManager; sourceTree = ""; @@ -223,11 +203,7 @@ 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, - 63C5ECC82AC467AF003904C4 /* TODO+CoreDataProperties.swift in Sources */, - 63C5ECC12AC466FB003904C4 /* CoreDataManager.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, - 63C5ECC42AC46751003904C4 /* TODO.xcdatamodeld in Sources */, - 63C5ECC72AC467AF003904C4 /* TODO+CoreDataClass.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -421,19 +397,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCVersionGroup section */ - 63C5ECC22AC46751003904C4 /* TODO.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */, - ); - currentVersion = 63C5ECC32AC46751003904C4 /* TODO.xcdatamodel */; - path = TODO.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; -/* End XCVersionGroup section */ }; rootObject = C7431EFA25F51E1D0094C4CF /* Project object */; } diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift deleted file mode 100644 index ba9d1b0f3..000000000 --- a/ProjectManager/ProjectManager/Model/CoreDataManager/CoreDataManager.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// CoreDataManager.swift -// ProjectManager -// -// Created by Hemg on 2023/09/27. -// - -import CoreData - -final class CoreDataManager { - private var todoList = [TODO]() - private var mainContext: NSManagedObjectContext { - return persistentContainer.viewContext - } - - func fetchTODO() -> [TODO] { - let request: NSFetchRequest = TODO.fetchRequest() - let sortByDate = NSSortDescriptor(key: "date", ascending: false) - request.sortDescriptors = [sortByDate] - - do { - let todos = try mainContext.fetch(request) - return todos - } catch { - fatalError() - } - } - - func createTODO() -> [TODO] { - let newTODO = TODO(context: mainContext) - newTODO.id = UUID() - newTODO.date = Date() - - return [newTODO] - } - - func deletTODO(_ todo: TODO?) { - guard let todo = todo else { - return - } - mainContext.delete(todo) - saveContext() - } - - lazy var persistentContainer: NSPersistentContainer = { - let container = NSPersistentContainer(name: "TODO") - container.loadPersistentStores(completionHandler: { (_, error) in - if let error = error as NSError? { - fatalError("Unresolved error \(error), \(error.userInfo)") - } - }) - return container - }() - - func saveContext () { - let context = persistentContainer.viewContext - if context.hasChanges { - do { - try context.save() - } catch { - let nsError = error as NSError - fatalError("Unresolved error \(nsError), \(nsError.userInfo)") - } - } - } -} diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift deleted file mode 100644 index b55154770..000000000 --- a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataClass.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// TODO+CoreDataClass.swift -// ProjectManager -// -// Created by Hemg on 2023/09/27. -// -// - -import CoreData - -@objc(TODO) -public class TODO: NSManagedObject {} diff --git a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift b/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift deleted file mode 100644 index 47656b061..000000000 --- a/ProjectManager/ProjectManager/Model/CoreDataManager/TODO+CoreDataProperties.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// TODO+CoreDataProperties.swift -// ProjectManager -// -// Created by Hemg on 2023/09/27. -// -// - -import CoreData - -extension TODO { - @nonobjc public class func fetchRequest() -> NSFetchRequest { - return NSFetchRequest(entityName: "TODO") - } - - @NSManaged public var title: String? - @NSManaged public var body: String? - @NSManaged public var date: Date? -} - -extension TODO : Identifiable { - @NSManaged public var id: UUID? -} From adeb2618ff3eb9ca7a5f209062465a683deaa84e Mon Sep 17 00:00:00 2001 From: hemg2 Date: Thu, 28 Sep 2023 23:38:33 +0900 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20=ED=85=8C=EC=9D=B4=EB=B8=94?= =?UTF-8?q?=EB=B7=B0=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/MainViewController.swift | 126 ++++++++++++++++-- .../Model/Entity/ProjectManager.swift | 2 +- .../ProjectManager/View/DescriptionCell.swift | 5 + .../ProjectManager/View/ListTitleCell.swift | 2 + 4 files changed, 125 insertions(+), 10 deletions(-) diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index b9f1e609a..19bfe2104 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -45,6 +45,8 @@ final class MainViewController: UIViewController { private var tableViewData: [UITableView: [Int: Int]] = [:] private var todoItems = [ProjectManager]() + private var doingItems = [ProjectManager]() + private var doneItems = [ProjectManager]() override func viewDidLoad() { super.viewDidLoad() @@ -68,7 +70,7 @@ final class MainViewController: UIViewController { view.addSubview(stackView) } - + private func setUpBarButtonItem() { let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addButton)) navigationItem.rightBarButtonItem = addButton @@ -81,7 +83,7 @@ final class MainViewController: UIViewController { backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) addTODOView.view.sendSubviewToBack(backgroundView) addTODOView.delegate = self - + present(navigationController, animated: true) } @@ -113,6 +115,48 @@ final class MainViewController: UIViewController { doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") tableViewData[doneTableView] = [0:1, 1:2] } + + private func moveToDoing(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + doingItems.append(item) + todoTableView.reloadData() + doingTableView.reloadData() + doneTableView.reloadData() + + } + + private func moveToDone(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } + + doneItems.append(item) + + todoTableView.reloadData() + doingTableView.reloadData() + doneTableView.reloadData() + } + + private func moveToTodo(_ item: ProjectManager) { + if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + todoItems.append(item) + + todoTableView.reloadData() + doingTableView.reloadData() + doneTableView.reloadData() + } } extension MainViewController: UITableViewDataSource { @@ -124,19 +168,19 @@ extension MainViewController: UITableViewDataSource { switch (tableView, section) { case (todoTableView, 0): return 1 - + case (todoTableView, 1): return todoItems.count case (doingTableView, 0): return 1 case (doingTableView, 1): - return 2 + return doingItems.count case (doneTableView, 0): return 1 case (doneTableView, 1): - return 2 + return doneItems.count default: return 0 @@ -162,25 +206,29 @@ extension MainViewController: UITableViewDataSource { case (doingTableView, 0): guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } - listCell.setModel(title: "DOING", count: 2) + listCell.setModel(title: "DOING", count: doingItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doingTableView, 1): guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + let doingItem = doingItems[indexPath.row] + descriptionCell.setModel(title: doingItem.title, body: doingItem.body, date: doingItem.date) return descriptionCell case (doneTableView, 0): guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } - listCell.setModel(title: "DONE", count: 3) + listCell.setModel(title: "DONE", count: doneItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doneTableView, 1): guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + let doneItem = doneItems[indexPath.row] + descriptionCell.setModel(title: doneItem.title, body: doneItem.body, date: doneItem.date) return descriptionCell default: @@ -190,13 +238,73 @@ extension MainViewController: UITableViewDataSource { } extension MainViewController: UITableViewDelegate { - + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let selectedCell: ProjectManager + switch (tableView, indexPath.section) { + case (todoTableView, 1): + selectedCell = todoItems[indexPath.row] + case (doingTableView, 1): + selectedCell = doingItems[indexPath.row] + case (doneTableView, 1): + selectedCell = doneItems[indexPath.row] + default: + return + } + + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + + switch tableView { + case todoTableView: + let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + self?.moveToDoing(selectedCell) + } + let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + self?.moveToDone(selectedCell) + } + alertController.addAction(moveToDoingAction) + alertController.addAction(moveToDoneAction) + + case doingTableView: + let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + self?.moveToTodo(selectedCell) + } + let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + self?.moveToDone(selectedCell) + } + alertController.addAction(moveToTodoAction) + alertController.addAction(moveToDoneAction) + + case doneTableView: + let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + self?.moveToTodo(selectedCell) + } + let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + self?.moveToDoing(selectedCell) + } + alertController.addAction(moveToTodoAction) + alertController.addAction(moveToDoingAction) + + default: + break + } + + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + alertController.addAction(cancelAction) + + if let popoverPresentationController = alertController.popoverPresentationController { + popoverPresentationController.sourceView = tableView + popoverPresentationController.sourceRect = tableView.rectForRow(at: indexPath) + } + + present(alertController, animated: true, completion: nil) + } } extension MainViewController: AddTodoDelegate { func didAddTodoItem(title: String, body: String, date: Date) { DataManager.shared.addTodoItem(title: title, body: body, date: date) - todoItems = DataManager.shared.leadTodoItem() + let newTodoItem = ProjectManager(title: title, body: body, date: date) + todoItems.append(newTodoItem) todoTableView.reloadData() } } diff --git a/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift b/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift index 2c08fab35..d4c6de670 100644 --- a/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift +++ b/ProjectManager/ProjectManager/Model/Entity/ProjectManager.swift @@ -7,7 +7,7 @@ import Foundation -struct ProjectManager { +struct ProjectManager: Equatable { let title: String let body: String let date: Date diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift index 790512d1d..b6f7b3e98 100644 --- a/ProjectManager/ProjectManager/View/DescriptionCell.swift +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -80,5 +80,10 @@ final class DescriptionCell: UITableViewCell { dateFormatter.dateFormat = "yyyy-MM-dd" let dateString = dateFormatter.string(from: date) dateLabel.text = dateString + + let currentDate = Date() + if currentDate > date { + dateLabel.textColor = .red + } } } diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift index b59ba30ab..a0e8fc313 100644 --- a/ProjectManager/ProjectManager/View/ListTitleCell.swift +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -12,6 +12,7 @@ final class ListTitleCell: UITableViewCell { let label = UILabel() label.font = .preferredFont(forTextStyle: .title1) label.translatesAutoresizingMaskIntoConstraints = false + label.numberOfLines = 1 return label }() @@ -20,6 +21,7 @@ final class ListTitleCell: UITableViewCell { let label = UILabel() label.font = .preferredFont(forTextStyle: .callout) label.translatesAutoresizingMaskIntoConstraints = false + label.numberOfLines = 3 return label }() From 9795be364241f75a922ec04e15dbe5015f936db7 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 29 Sep 2023 14:22:22 +0900 Subject: [PATCH 12/25] =?UTF-8?q?feat:=20=EC=88=98=EC=A0=95=EC=A7=84?= =?UTF-8?q?=ED=96=89(=EB=8D=B8=EB=A6=AC=EA=B2=8C=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=EC=B6=94=EA=B0=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 8 +- ...ller.swift => AddTodoViewController.swift} | 72 +++++-- .../Controller/MainViewController.swift | 198 ++++++++++++------ .../Model/Entity/ProjectManager.swift | 6 +- 4 files changed, 200 insertions(+), 84 deletions(-) rename ProjectManager/ProjectManager/Controller/{AddTODOViewController.swift => AddTodoViewController.swift} (67%) diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 0794753ca..c0f08c926 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -9,7 +9,7 @@ /* Begin PBXBuildFile section */ 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */; }; 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */; }; - 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */; }; + 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */; }; 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; @@ -22,7 +22,7 @@ /* Begin PBXFileReference section */ 63C5ECB52AC1949A003904C4 /* ListTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTitleCell.swift; sourceTree = ""; }; 63C5ECB72AC2B957003904C4 /* DescriptionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescriptionCell.swift; sourceTree = ""; }; - 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTODOViewController.swift; sourceTree = ""; }; + 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTodoViewController.swift; sourceTree = ""; }; 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -58,7 +58,7 @@ isa = PBXGroup; children = ( C7431F0925F51E1D0094C4CF /* MainViewController.swift */, - 63C5ECB92AC2FE9A003904C4 /* AddTODOViewController.swift */, + 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */, ); path = Controller; sourceTree = ""; @@ -200,7 +200,7 @@ 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, - 63C5ECBA2AC2FE9A003904C4 /* AddTODOViewController.swift in Sources */, + 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift b/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift similarity index 67% rename from ProjectManager/ProjectManager/Controller/AddTODOViewController.swift rename to ProjectManager/ProjectManager/Controller/AddTodoViewController.swift index e01d81e6c..439752c19 100644 --- a/ProjectManager/ProjectManager/Controller/AddTODOViewController.swift +++ b/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift @@ -1,5 +1,5 @@ // -// AddTODOViewController.swift +// AddTodoViewController.swift // ProjectManager // // Created by Hemg on 2023/09/26. @@ -9,9 +9,10 @@ import UIKit protocol AddTodoDelegate: AnyObject { func didAddTodoItem(title: String, body: String, date: Date) + func didEditTodoItem(title: String, body: String, date: Date, index: Int) } -final class AddTODOViewController: UIViewController { +final class AddTodoViewController: UIViewController { private let titleTextField: UITextField = { let textField = UITextField() textField.translatesAutoresizingMaskIntoConstraints = false @@ -45,7 +46,24 @@ final class AddTODOViewController: UIViewController { }() weak var delegate: AddTodoDelegate? - + private var todoItems: ProjectManager? + private var isNew: Bool + + init() { + self.isNew = true + super.init(nibName: nil, bundle: nil) + } + + init(todoItems: ProjectManager?) { + self.isNew = false + self.todoItems = todoItems + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func viewDidLoad() { super.viewDidLoad() @@ -53,6 +71,7 @@ final class AddTODOViewController: UIViewController { setUpBarButtonItem() configureUI() setUpViewLayout() + setUpItemValues() } private func setUpViewController() { @@ -65,8 +84,21 @@ final class AddTODOViewController: UIViewController { let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneButton)) navigationItem.rightBarButtonItem = doneButton - let cancel = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(cancelButton)) - navigationItem.leftBarButtonItem = cancel + if isNew == true { + let cancelButton = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(cancelButton)) + navigationItem.leftBarButtonItem = cancelButton + } else { + let editButton = UIBarButtonItem(title: "Edit", style: .done, target: self, action: #selector(editButton)) + navigationItem.leftBarButtonItem = editButton + } + } + + private func setUpItemValues() { + if let todoItems = todoItems { + titleTextField.text = todoItems.title + bodyTextView.text = todoItems.body + datePicker.date = todoItems.date + } } @objc private func doneButton() { @@ -78,12 +110,17 @@ final class AddTODOViewController: UIViewController { dismiss(animated: true) } + @objc private func editButton() { + setUpItemText() + dismiss(animated: true) + } + private func configureUI() { view.addSubview(titleTextField) view.addSubview(bodyTextView) view.addSubview(datePicker) } - + private func setUpViewLayout() { NSLayoutConstraint.activate([ titleTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), @@ -102,17 +139,26 @@ final class AddTODOViewController: UIViewController { } private func setUpItemText() { - let date = datePicker.date - guard let titleText = titleTextField.text, - let bodyText = bodyTextView.text else { - return + if isNew == false { + let date = datePicker.date + guard let titleText = titleTextField.text, + let bodyText = bodyTextView.text else { return } + todoItems?.title = titleText + todoItems?.body = bodyText + todoItems?.date = date + + delegate?.didEditTodoItem(title: titleText, body: bodyText, date: date, index: 0) + } else { + let date = datePicker.date + guard let titleText = titleTextField.text, + let bodyText = bodyTextView.text else { return } + + delegate?.didAddTodoItem(title: titleText, body: bodyText, date: date) } - - delegate?.didAddTodoItem(title: titleText, body: bodyText, date: date) } } -extension AddTODOViewController: UITextViewDelegate { +extension AddTodoViewController: UITextViewDelegate { func textViewDidBeginEditing(_ textView: UITextView) { if textView.text == "여기는 할일 내용 입력하는 곳입니다." { textView.text = "" diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 19bfe2104..942127fd5 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -56,6 +56,7 @@ final class MainViewController: UIViewController { configureUI() setUpTableViewLayout() setUpTableView() + addPressGesture(to: [todoTableView, doingTableView, doneTableView]) } private func setUpViewController() { @@ -76,17 +77,6 @@ final class MainViewController: UIViewController { navigationItem.rightBarButtonItem = addButton } - @objc private func addButton() { - let addTODOView = AddTODOViewController() - let navigationController = UINavigationController(rootViewController: addTODOView) - let backgroundView = UIView(frame: view.bounds) - backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) - addTODOView.view.sendSubviewToBack(backgroundView) - addTODOView.delegate = self - - present(navigationController, animated: true) - } - private func setUpTableViewLayout() { NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), @@ -115,7 +105,10 @@ final class MainViewController: UIViewController { doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") tableViewData[doneTableView] = [0:1, 1:2] } - +} + +// MARK: Action +extension MainViewController { private func moveToDoing(_ item: ProjectManager) { if let index = todoItems.firstIndex(where: { $0 == item }) { todoItems.remove(at: index) @@ -127,7 +120,6 @@ final class MainViewController: UIViewController { todoTableView.reloadData() doingTableView.reloadData() doneTableView.reloadData() - } private func moveToDone(_ item: ProjectManager) { @@ -138,7 +130,6 @@ final class MainViewController: UIViewController { } doneItems.append(item) - todoTableView.reloadData() doingTableView.reloadData() doneTableView.reloadData() @@ -152,13 +143,107 @@ final class MainViewController: UIViewController { } todoItems.append(item) - todoTableView.reloadData() doingTableView.reloadData() doneTableView.reloadData() } + + private func addPressGesture(to tableViews: [UITableView]) { + for tableView in tableViews { + let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handlePress(_:))) + longPressGestureRecognizer.cancelsTouchesInView = true + tableView.addGestureRecognizer(longPressGestureRecognizer) + } + } + + private func updateItem(in items: inout [ProjectManager], at index: Int, with title: String, body: String, date: Date, tableView: UITableView) { + guard index < items.count else { return } + items[index].title = title + items[index].body = body + items[index].date = date + tableView.reloadData() + } + + @objc private func addButton() { + let addTODOView = AddTodoViewController() + let navigationController = UINavigationController(rootViewController: addTODOView) + let backgroundView = UIView(frame: view.bounds) + backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) + addTODOView.view.sendSubviewToBack(backgroundView) + addTODOView.delegate = self + + present(navigationController, animated: true) + } + + @objc func handlePress(_ gestureRecognizer: UILongPressGestureRecognizer) { + if gestureRecognizer.state == .began { + let point = gestureRecognizer.location(in: gestureRecognizer.view) + if let tableView = gestureRecognizer.view as? UITableView, + let indexPath = tableView.indexPathForRow(at: point) { + let selectedCell: ProjectManager + switch (tableView, indexPath.section) { + case (todoTableView, 1): + selectedCell = todoItems[indexPath.row] + case (doingTableView, 1): + selectedCell = doingItems[indexPath.row] + case (doneTableView, 1): + selectedCell = doneItems[indexPath.row] + default: + return + } + + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + + switch tableView { + case todoTableView: + let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + self?.moveToDoing(selectedCell) + } + let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + self?.moveToDone(selectedCell) + } + alertController.addAction(moveToDoingAction) + alertController.addAction(moveToDoneAction) + + case doingTableView: + let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + self?.moveToTodo(selectedCell) + } + let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + self?.moveToDone(selectedCell) + } + alertController.addAction(moveToTodoAction) + alertController.addAction(moveToDoneAction) + + case doneTableView: + let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + self?.moveToTodo(selectedCell) + } + let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + self?.moveToDoing(selectedCell) + } + alertController.addAction(moveToTodoAction) + alertController.addAction(moveToDoingAction) + + default: + break + } + + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + alertController.addAction(cancelAction) + + if let popoverPresentationController = alertController.popoverPresentationController { + popoverPresentationController.sourceView = tableView + popoverPresentationController.sourceRect = tableView.rectForRow(at: indexPath) + } + + present(alertController, animated: true) + } + } + } } +// MARK: UITableViewDataSource extension MainViewController: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 2 @@ -201,6 +286,7 @@ extension MainViewController: UITableViewDataSource { let todoItem = todoItems[indexPath.row] descriptionCell.setModel(title: todoItem.title, body: todoItem.body, date: todoItem.date) + descriptionCell.isUserInteractionEnabled = true return descriptionCell case (doingTableView, 0): @@ -215,6 +301,7 @@ extension MainViewController: UITableViewDataSource { let doingItem = doingItems[indexPath.row] descriptionCell.setModel(title: doingItem.title, body: doingItem.body, date: doingItem.date) + descriptionCell.isUserInteractionEnabled = true return descriptionCell case (doneTableView, 0): @@ -229,6 +316,7 @@ extension MainViewController: UITableViewDataSource { let doneItem = doneItems[indexPath.row] descriptionCell.setModel(title: doneItem.title, body: doneItem.body, date: doneItem.date) + descriptionCell.isUserInteractionEnabled = true return descriptionCell default: @@ -237,66 +325,28 @@ extension MainViewController: UITableViewDataSource { } } +// MARK: UITableViewDelegate extension MainViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let selectedCell: ProjectManager - switch (tableView, indexPath.section) { - case (todoTableView, 1): - selectedCell = todoItems[indexPath.row] - case (doingTableView, 1): - selectedCell = doingItems[indexPath.row] - case (doneTableView, 1): - selectedCell = doneItems[indexPath.row] - default: - return - } - - let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + tableView.deselectRow(at: indexPath, animated: true) + var selectedTodoData: ProjectManager switch tableView { case todoTableView: - let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - alertController.addAction(moveToDoingAction) - alertController.addAction(moveToDoneAction) - + selectedTodoData = todoItems[indexPath.row] case doingTableView: - let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) - } - let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - alertController.addAction(moveToTodoAction) - alertController.addAction(moveToDoneAction) - + selectedTodoData = doingItems[indexPath.row] case doneTableView: - let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) - } - let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - alertController.addAction(moveToTodoAction) - alertController.addAction(moveToDoingAction) - + selectedTodoData = doneItems[indexPath.row] default: - break + return } - let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) - alertController.addAction(cancelAction) + let addTodoView = AddTodoViewController(todoItems: selectedTodoData) + let navigationController = UINavigationController(rootViewController: addTodoView) - if let popoverPresentationController = alertController.popoverPresentationController { - popoverPresentationController.sourceView = tableView - popoverPresentationController.sourceRect = tableView.rectForRow(at: indexPath) - } - - present(alertController, animated: true, completion: nil) + addTodoView.delegate = self + present(navigationController, animated: true) } } @@ -307,4 +357,24 @@ extension MainViewController: AddTodoDelegate { todoItems.append(newTodoItem) todoTableView.reloadData() } + + func didEditTodoItem(title: String, body: String, date: Date, index: Int) { + switch index { + case 0.. Date: Fri, 29 Sep 2023 15:59:54 +0900 Subject: [PATCH 13/25] =?UTF-8?q?feat:=20=EB=84=A4=EC=9E=84=EC=8A=A4?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 16 ++++++++ .../Controller/MainViewController.swift | 38 ++++++++++--------- .../Model/Namespace/AlertNamespace.swift | 12 ++++++ .../Model/Namespace/ReuseIdentifier.swift | 11 ++++++ 4 files changed, 59 insertions(+), 18 deletions(-) create mode 100644 ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift create mode 100644 ProjectManager/ProjectManager/Model/Namespace/ReuseIdentifier.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index c0f08c926..cba0b582d 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */; }; 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; + 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */; }; + 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -25,6 +27,8 @@ 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddTodoViewController.swift; sourceTree = ""; }; 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; + 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifier.swift; sourceTree = ""; }; + 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -76,6 +80,7 @@ 63C5ECBB2AC45243003904C4 /* Model */ = { isa = PBXGroup; children = ( + 63CC815E2AC6AA3600E6355F /* Namespace */, 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, ); @@ -98,6 +103,15 @@ path = DataManager; sourceTree = ""; }; + 63CC815E2AC6AA3600E6355F /* Namespace */ = { + isa = PBXGroup; + children = ( + 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */, + 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */, + ); + path = Namespace; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -203,6 +217,8 @@ 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, + 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */, + 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 942127fd5..863f980b1 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -89,20 +89,20 @@ final class MainViewController: UIViewController { private func setUpTableView() { todoTableView.dataSource = self todoTableView.delegate = self - todoTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") - todoTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") + todoTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) + todoTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) tableViewData[todoTableView] = [0:1, 1:2] doingTableView.dataSource = self doingTableView.delegate = self - doingTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") - doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") + doingTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) + doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) tableViewData[doingTableView] = [0:1, 1:2] doneTableView.dataSource = self doneTableView.delegate = self - doneTableView.register(ListTitleCell.self, forCellReuseIdentifier: "listTitleCell") - doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: "descriptionCell") + doneTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) + doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) tableViewData[doneTableView] = [0:1, 1:2] } } @@ -196,30 +196,30 @@ extension MainViewController { switch tableView { case todoTableView: - let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + let moveToDoingAction = UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in self?.moveToDoing(selectedCell) } - let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + let moveToDoneAction = UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in self?.moveToDone(selectedCell) } alertController.addAction(moveToDoingAction) alertController.addAction(moveToDoneAction) case doingTableView: - let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + let moveToTodoAction = UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in self?.moveToTodo(selectedCell) } - let moveToDoneAction = UIAlertAction(title: "Move to DONE", style: .default) { [weak self] _ in + let moveToDoneAction = UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in self?.moveToDone(selectedCell) } alertController.addAction(moveToTodoAction) alertController.addAction(moveToDoneAction) case doneTableView: - let moveToTodoAction = UIAlertAction(title: "Move to TODO", style: .default) { [weak self] _ in + let moveToTodoAction = UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in self?.moveToTodo(selectedCell) } - let moveToDoingAction = UIAlertAction(title: "Move to DOING", style: .default) { [weak self] _ in + let moveToDoingAction = UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in self?.moveToDoing(selectedCell) } alertController.addAction(moveToTodoAction) @@ -275,14 +275,14 @@ extension MainViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch (tableView, indexPath.section) { case (todoTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } listCell.setModel(title: "TODO", count: todoItems.count) listCell.backgroundColor = .systemGray5 return listCell case (todoTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } let todoItem = todoItems[indexPath.row] descriptionCell.setModel(title: todoItem.title, body: todoItem.body, date: todoItem.date) @@ -290,14 +290,14 @@ extension MainViewController: UITableViewDataSource { return descriptionCell case (doingTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } listCell.setModel(title: "DOING", count: doingItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doingTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } let doingItem = doingItems[indexPath.row] descriptionCell.setModel(title: doingItem.title, body: doingItem.body, date: doingItem.date) @@ -305,14 +305,14 @@ extension MainViewController: UITableViewDataSource { return descriptionCell case (doneTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: "listTitleCell", for: indexPath) as? ListTitleCell else { return UITableViewCell() } + guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } listCell.setModel(title: "DONE", count: doneItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doneTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: "descriptionCell", for: indexPath) as? DescriptionCell else { return UITableViewCell() } + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } let doneItem = doneItems[indexPath.row] descriptionCell.setModel(title: doneItem.title, body: doneItem.body, date: doneItem.date) @@ -329,6 +329,8 @@ extension MainViewController: UITableViewDataSource { extension MainViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) + + guard indexPath.section == 1 else { return } var selectedTodoData: ProjectManager switch tableView { diff --git a/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift b/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift new file mode 100644 index 000000000..b63e8e103 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift @@ -0,0 +1,12 @@ +// +// AlertNamespace.swift +// ProjectManager +// +// Created by Hemg on 2023/09/29. +// + +enum AlertNamespace { + static let moveToDoing = "Move to DOING" + static let moveToDone = "Move to DONE" + static let moveToTodo = "Move to TODO" +} diff --git a/ProjectManager/ProjectManager/Model/Namespace/ReuseIdentifier.swift b/ProjectManager/ProjectManager/Model/Namespace/ReuseIdentifier.swift new file mode 100644 index 000000000..58393a3d4 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Namespace/ReuseIdentifier.swift @@ -0,0 +1,11 @@ +// +// ReuseIdentifier.swift +// ProjectManager +// +// Created by Hemg on 2023/09/29. +// + +enum ReuseIdentifier { + static let listTitleCell = "ListTitleCell" + static let descriptionCell = "DescriptionCell" +} From 3e630d220b122a35ce7ee2d83e89f122ed7c2d7f Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 29 Sep 2023 17:07:14 +0900 Subject: [PATCH 14/25] =?UTF-8?q?feat:=20dataManager=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager/App/SceneDelegate.swift | 3 ++- .../Controller/AddTodoViewController.swift | 7 +++++-- .../Controller/MainViewController.swift | 16 +++++++++++++--- .../Model/DataManager/DataManager.swift | 14 ++++++-------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/ProjectManager/ProjectManager/App/SceneDelegate.swift b/ProjectManager/ProjectManager/App/SceneDelegate.swift index 702cf323c..3b3bd4d8a 100644 --- a/ProjectManager/ProjectManager/App/SceneDelegate.swift +++ b/ProjectManager/ProjectManager/App/SceneDelegate.swift @@ -13,9 +13,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } + let dataManager = DataManager() window = UIWindow(windowScene: windowScene) - let mainViewController = MainViewController() + let mainViewController = MainViewController(dataManager: dataManager) let navigationController = UINavigationController(rootViewController: mainViewController) window?.rootViewController = navigationController window?.makeKeyAndVisible() diff --git a/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift b/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift index 439752c19..7717fff8e 100644 --- a/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift +++ b/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift @@ -47,16 +47,19 @@ final class AddTodoViewController: UIViewController { weak var delegate: AddTodoDelegate? private var todoItems: ProjectManager? + private let dataManager: DataManagerProtocol private var isNew: Bool - init() { + init(dataManager: DataManagerProtocol) { + self.dataManager = dataManager self.isNew = true super.init(nibName: nil, bundle: nil) } - init(todoItems: ProjectManager?) { + init(todoItems: ProjectManager?, dataManager: DataManagerProtocol) { self.isNew = false self.todoItems = todoItems + self.dataManager = dataManager super.init(nibName: nil, bundle: nil) } diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 863f980b1..9d8c95733 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -47,6 +47,16 @@ final class MainViewController: UIViewController { private var todoItems = [ProjectManager]() private var doingItems = [ProjectManager]() private var doneItems = [ProjectManager]() + private let dataManager: DataManagerProtocol + + init(dataManager: DataManagerProtocol) { + self.dataManager = dataManager + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } override func viewDidLoad() { super.viewDidLoad() @@ -165,7 +175,7 @@ extension MainViewController { } @objc private func addButton() { - let addTODOView = AddTodoViewController() + let addTODOView = AddTodoViewController(dataManager: dataManager) let navigationController = UINavigationController(rootViewController: addTODOView) let backgroundView = UIView(frame: view.bounds) backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) @@ -344,7 +354,7 @@ extension MainViewController: UITableViewDelegate { return } - let addTodoView = AddTodoViewController(todoItems: selectedTodoData) + let addTodoView = AddTodoViewController(todoItems: selectedTodoData, dataManager: dataManager) let navigationController = UINavigationController(rootViewController: addTodoView) addTodoView.delegate = self @@ -354,7 +364,7 @@ extension MainViewController: UITableViewDelegate { extension MainViewController: AddTodoDelegate { func didAddTodoItem(title: String, body: String, date: Date) { - DataManager.shared.addTodoItem(title: title, body: body, date: date) + dataManager.addTodoItem(title: title, body: body, date: date) let newTodoItem = ProjectManager(title: title, body: body, date: date) todoItems.append(newTodoItem) todoTableView.reloadData() diff --git a/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift index ad4536cc6..f415edab0 100644 --- a/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift +++ b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift @@ -7,17 +7,15 @@ import Foundation -final class DataManager { - static let shared = DataManager() +protocol DataManagerProtocol { + func addTodoItem(title: String, body: String, date: Date) +} + +final class DataManager: DataManagerProtocol { private var todoItems = [ProjectManager]() - private init() {} func addTodoItem(title: String, body: String, date: Date) { - let newItem = ProjectManager(title: title, body: body, date: date) + let newItem = ProjectManager(title: title, body: body, date: date) todoItems.append(newItem) } - - func leadTodoItem() -> [ProjectManager] { - return todoItems - } } From 68d0c7b01cae8a80577804913417588b2b9a58f5 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 29 Sep 2023 18:26:05 +0900 Subject: [PATCH 15/25] =?UTF-8?q?feat:=20configureTableView=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=86=A0=EC=BD=9C=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 16 +++ .../Controller/MainViewController.swift | 99 +++++++------------ .../Model/Protocol/AlertActionCreatable.swift | 14 +++ .../Protocol/ConfigurableTableView.swift | 21 ++++ 4 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift create mode 100644 ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index cba0b582d..f26d81361 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */; }; 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; + 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; + 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -29,6 +31,8 @@ 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifier.swift; sourceTree = ""; }; 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; + 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; + 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -80,6 +84,7 @@ 63C5ECBB2AC45243003904C4 /* Model */ = { isa = PBXGroup; children = ( + 63CC81662AC6C1C800E6355F /* Protocol */, 63CC815E2AC6AA3600E6355F /* Namespace */, 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, @@ -112,6 +117,15 @@ path = Namespace; sourceTree = ""; }; + 63CC81662AC6C1C800E6355F /* Protocol */ = { + isa = PBXGroup; + children = ( + 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, + 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */, + ); + path = Protocol; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -210,10 +224,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, + 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */, 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 9d8c95733..874bef3f8 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -6,7 +6,7 @@ import UIKit -final class MainViewController: UIViewController { +final class MainViewController: UIViewController, ConfigurableTableView { private let todoTableView: UITableView = { let tableView = UITableView() tableView.translatesAutoresizingMaskIntoConstraints = false @@ -43,7 +43,6 @@ final class MainViewController: UIViewController { return stackView }() - private var tableViewData: [UITableView: [Int: Int]] = [:] private var todoItems = [ProjectManager]() private var doingItems = [ProjectManager]() private var doneItems = [ProjectManager]() @@ -97,28 +96,38 @@ final class MainViewController: UIViewController { } private func setUpTableView() { - todoTableView.dataSource = self - todoTableView.delegate = self - todoTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) - todoTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) - tableViewData[todoTableView] = [0:1, 1:2] - - doingTableView.dataSource = self - doingTableView.delegate = self - doingTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) - doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) - tableViewData[doingTableView] = [0:1, 1:2] - - doneTableView.dataSource = self - doneTableView.delegate = self - doneTableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) - doneTableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) - tableViewData[doneTableView] = [0:1, 1:2] + configureTableView(todoTableView) + configureTableView(doingTableView) + configureTableView(doneTableView) } } // MARK: Action -extension MainViewController { +extension MainViewController: AlertActionCreator { + private func setUpTableViewReloadData() { + todoTableView.reloadData() + doingTableView.reloadData() + doneTableView.reloadData() + } + + func createMoveToTodoAction(_ selectedCell: ProjectManager) -> UIAlertAction { + return UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in + self?.moveToTodo(selectedCell) + } + } + + func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction { + return UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in + self?.moveToDoing(selectedCell) + } + } + + func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction { + return UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in + self?.moveToDone(selectedCell) + } + } + private func moveToDoing(_ item: ProjectManager) { if let index = todoItems.firstIndex(where: { $0 == item }) { todoItems.remove(at: index) @@ -127,9 +136,7 @@ extension MainViewController { } doingItems.append(item) - todoTableView.reloadData() - doingTableView.reloadData() - doneTableView.reloadData() + setUpTableViewReloadData() } private func moveToDone(_ item: ProjectManager) { @@ -140,9 +147,7 @@ extension MainViewController { } doneItems.append(item) - todoTableView.reloadData() - doingTableView.reloadData() - doneTableView.reloadData() + setUpTableViewReloadData() } private func moveToTodo(_ item: ProjectManager) { @@ -153,9 +158,7 @@ extension MainViewController { } todoItems.append(item) - todoTableView.reloadData() - doingTableView.reloadData() - doneTableView.reloadData() + setUpTableViewReloadData() } private func addPressGesture(to tableViews: [UITableView]) { @@ -166,14 +169,6 @@ extension MainViewController { } } - private func updateItem(in items: inout [ProjectManager], at index: Int, with title: String, body: String, date: Date, tableView: UITableView) { - guard index < items.count else { return } - items[index].title = title - items[index].body = body - items[index].date = date - tableView.reloadData() - } - @objc private func addButton() { let addTODOView = AddTodoViewController(dataManager: dataManager) let navigationController = UINavigationController(rootViewController: addTODOView) @@ -206,34 +201,16 @@ extension MainViewController { switch tableView { case todoTableView: - let moveToDoingAction = UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - let moveToDoneAction = UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - alertController.addAction(moveToDoingAction) - alertController.addAction(moveToDoneAction) + alertController.addAction(createMoveToDoingAction(selectedCell)) + alertController.addAction(createMoveToDoneAction(selectedCell)) case doingTableView: - let moveToTodoAction = UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) - } - let moveToDoneAction = UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - alertController.addAction(moveToTodoAction) - alertController.addAction(moveToDoneAction) + alertController.addAction(createMoveToTodoAction(selectedCell)) + alertController.addAction(createMoveToDoneAction(selectedCell)) case doneTableView: - let moveToTodoAction = UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) - } - let moveToDoingAction = UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - alertController.addAction(moveToTodoAction) - alertController.addAction(moveToDoingAction) + alertController.addAction(createMoveToTodoAction(selectedCell)) + alertController.addAction(createMoveToDoingAction(selectedCell)) default: break diff --git a/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift b/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift new file mode 100644 index 000000000..0b802daf3 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift @@ -0,0 +1,14 @@ +// +// AlertActionCreatable.swift +// ProjectManager +// +// Created by Hemg on 2023/09/29. +// + +import UIKit + +protocol AlertActionCreator { + func createMoveToTodoAction(_ selectedCell: ProjectManager) -> UIAlertAction + func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction + func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction +} diff --git a/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift b/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift new file mode 100644 index 000000000..7627241d7 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift @@ -0,0 +1,21 @@ +// +// ConfigurableTableView.swift +// ProjectManager +// +// Created by Hemg on 2023/09/29. +// + +import UIKit + +protocol ConfigurableTableView { + func configureTableView(_ tableView: UITableView) +} + +extension ConfigurableTableView { + func configureTableView(_ tableView: UITableView) { + tableView.dataSource = self as? UITableViewDataSource + tableView.delegate = self as? UITableViewDelegate + tableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) + tableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) + } +} From 9f2006c5b237d47a747c0b9f010e283352981796 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 29 Sep 2023 18:55:39 +0900 Subject: [PATCH 16/25] =?UTF-8?q?feat:=20ItemUpdatable=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 4 +++ .../Controller/MainViewController.swift | 17 +++-------- .../Model/Protocol/ItemUpdatable.swift | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 ProjectManager/ProjectManager/Model/Protocol/ItemUpdatable.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index f26d81361..012d56b1a 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */; }; + 63CC816C2AC6D24600E6355F /* ItemUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -33,6 +34,7 @@ 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; + 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemUpdatable.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -122,6 +124,7 @@ children = ( 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */, + 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */, ); path = Protocol; sourceTree = ""; @@ -224,6 +227,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 63CC816C2AC6D24600E6355F /* ItemUpdatable.swift in Sources */, 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 874bef3f8..1f2c3dcd3 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -339,7 +339,7 @@ extension MainViewController: UITableViewDelegate { } } -extension MainViewController: AddTodoDelegate { +extension MainViewController: AddTodoDelegate, ItemUpdatable { func didAddTodoItem(title: String, body: String, date: Date) { dataManager.addTodoItem(title: title, body: body, date: date) let newTodoItem = ProjectManager(title: title, body: body, date: date) @@ -350,20 +350,11 @@ extension MainViewController: AddTodoDelegate { func didEditTodoItem(title: String, body: String, date: Date, index: Int) { switch index { case 0.. [ProjectManager] +} + +extension ItemUpdatable { + func updateItemInArray(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { + guard var mutableItems = items, + index >= 0 && index < mutableItems.count else { + return items ?? [] + } + + mutableItems[index].title = title + mutableItems[index].body = body + mutableItems[index].date = date + tableView.reloadData() + + return mutableItems + } +} From b8462e4b060eb7df1c0ef3ca9dde5621d43b0c48 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 29 Sep 2023 23:45:25 +0900 Subject: [PATCH 17/25] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 4 ++ .../Controller/MainViewController.swift | 47 +++++-------------- .../Model/Namespace/CellTitleNamespace.swift | 12 +++++ .../Model/Protocol/ItemUpdatable.swift | 4 +- 4 files changed, 29 insertions(+), 38 deletions(-) create mode 100644 ProjectManager/ProjectManager/Model/Namespace/CellTitleNamespace.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 012d56b1a..38595a245 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */; }; 63CC816C2AC6D24600E6355F /* ItemUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */; }; + 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -35,6 +36,7 @@ 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemUpdatable.swift; sourceTree = ""; }; + 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellTitleNamespace.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -115,6 +117,7 @@ children = ( 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */, 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */, + 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */, ); path = Namespace; sourceTree = ""; @@ -231,6 +234,7 @@ 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, + 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 1f2c3dcd3..bd4b01cc3 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -203,15 +203,12 @@ extension MainViewController: AlertActionCreator { case todoTableView: alertController.addAction(createMoveToDoingAction(selectedCell)) alertController.addAction(createMoveToDoneAction(selectedCell)) - case doingTableView: alertController.addAction(createMoveToTodoAction(selectedCell)) alertController.addAction(createMoveToDoneAction(selectedCell)) - case doneTableView: alertController.addAction(createMoveToTodoAction(selectedCell)) alertController.addAction(createMoveToDoingAction(selectedCell)) - default: break } @@ -238,74 +235,52 @@ extension MainViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch (tableView, section) { - case (todoTableView, 0): + case (todoTableView, 0), (doingTableView, 0), (doneTableView, 0): return 1 - case (todoTableView, 1): return todoItems.count - - case (doingTableView, 0): - return 1 case (doingTableView, 1): return doingItems.count - - case (doneTableView, 0): - return 1 case (doneTableView, 1): return doneItems.count - default: return 0 } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } + + guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } + switch (tableView, indexPath.section) { case (todoTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } - - listCell.setModel(title: "TODO", count: todoItems.count) + listCell.setModel(title: CellTitleNamespace.todo, count: todoItems.count) listCell.backgroundColor = .systemGray5 return listCell - case (todoTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } - let todoItem = todoItems[indexPath.row] descriptionCell.setModel(title: todoItem.title, body: todoItem.body, date: todoItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell - case (doingTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } - - listCell.setModel(title: "DOING", count: doingItems.count) + listCell.setModel(title: CellTitleNamespace.doing, count: doingItems.count) listCell.backgroundColor = .systemGray5 return listCell - case (doingTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } - let doingItem = doingItems[indexPath.row] descriptionCell.setModel(title: doingItem.title, body: doingItem.body, date: doingItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell - case (doneTableView, 0): - guard let listCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.listTitleCell, for: indexPath) as? ListTitleCell else { return UITableViewCell() } - - listCell.setModel(title: "DONE", count: doneItems.count) + listCell.setModel(title: CellTitleNamespace.done, count: doneItems.count) listCell.backgroundColor = .systemGray5 return listCell - case (doneTableView, 1): - guard let descriptionCell = todoTableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.descriptionCell, for: indexPath) as? DescriptionCell else { return UITableViewCell() } - let doneItem = doneItems[indexPath.row] descriptionCell.setModel(title: doneItem.title, body: doneItem.body, date: doneItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell - default: return UITableViewCell() } @@ -350,11 +325,11 @@ extension MainViewController: AddTodoDelegate, ItemUpdatable { func didEditTodoItem(title: String, body: String, date: Date, index: Int) { switch index { case 0.. [ProjectManager] + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] } extension ItemUpdatable { - func updateItemInArray(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { guard var mutableItems = items, index >= 0 && index < mutableItems.count else { return items ?? [] From 640478abf8464a3037011716b3bb7c0923c5f4d2 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Sat, 30 Sep 2023 16:00:17 +0900 Subject: [PATCH 18/25] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=86=A0?= =?UTF-8?q?=EC=BD=9C=20->=20=EC=9C=A0=EC=8A=A4=EC=BC=80=EC=9D=B4=EC=8A=A4?= =?UTF-8?q?=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 24 ++++++++++++------- .../ProjectManager/App/SceneDelegate.swift | 5 ++-- .../Controller/MainViewController.swift | 14 ++++++----- .../MainViewControllerUseCase.swift} | 8 +++---- 4 files changed, 31 insertions(+), 20 deletions(-) rename ProjectManager/ProjectManager/{Model/Protocol/ItemUpdatable.swift => UseCase/MainViewControllerUseCase.swift} (78%) diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 38595a245..504a41404 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -15,9 +15,9 @@ 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */; }; 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; - 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */; }; - 63CC816C2AC6D24600E6355F /* ItemUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */; }; 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */; }; + 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */; }; + 63CC81732AC7FA0200E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -34,9 +34,9 @@ 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifier.swift; sourceTree = ""; }; 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; - 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; - 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemUpdatable.swift; sourceTree = ""; }; 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellTitleNamespace.swift; sourceTree = ""; }; + 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; + 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -126,12 +126,19 @@ isa = PBXGroup; children = ( 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, - 63CC81692AC6C99F00E6355F /* ConfigurableTableView.swift */, - 63CC816B2AC6D24600E6355F /* ItemUpdatable.swift */, + 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */, ); path = Protocol; sourceTree = ""; }; + 63CC816F2AC7F59700E6355F /* UseCase */ = { + isa = PBXGroup; + children = ( + 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */, + ); + path = UseCase; + sourceTree = ""; + }; C7431EF925F51E1D0094C4CF = { isa = PBXGroup; children = ( @@ -151,6 +158,7 @@ C7431F0425F51E1D0094C4CF /* ProjectManager */ = { isa = PBXGroup; children = ( + 63CC816F2AC7F59700E6355F /* UseCase */, 63C5ECBB2AC45243003904C4 /* Model */, 63C5ECB22AC1944F003904C4 /* App */, 63C5ECB32AC19459003904C4 /* Controller */, @@ -230,18 +238,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 63CC816C2AC6D24600E6355F /* ItemUpdatable.swift in Sources */, 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, + 63CC81732AC7FA0200E6355F /* ConfigurableTableView.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, - 63CC816A2AC6C99F00E6355F /* ConfigurableTableView.swift in Sources */, 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */, + 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */, 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, ); diff --git a/ProjectManager/ProjectManager/App/SceneDelegate.swift b/ProjectManager/ProjectManager/App/SceneDelegate.swift index 3b3bd4d8a..5474c43ea 100644 --- a/ProjectManager/ProjectManager/App/SceneDelegate.swift +++ b/ProjectManager/ProjectManager/App/SceneDelegate.swift @@ -13,10 +13,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } - let dataManager = DataManager() + let dataManager: DataManagerProtocol = DataManager() + let usecase: MainViewControllerUseCase = MainViewControllerUseCaseImplementation() window = UIWindow(windowScene: windowScene) - let mainViewController = MainViewController(dataManager: dataManager) + let mainViewController = MainViewController(dataManager: dataManager, usecase: usecase) let navigationController = UINavigationController(rootViewController: mainViewController) window?.rootViewController = navigationController window?.makeKeyAndVisible() diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index bd4b01cc3..324a8dd94 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -47,9 +47,11 @@ final class MainViewController: UIViewController, ConfigurableTableView { private var doingItems = [ProjectManager]() private var doneItems = [ProjectManager]() private let dataManager: DataManagerProtocol + private let usecase: MainViewControllerUseCase - init(dataManager: DataManagerProtocol) { + init(dataManager: DataManagerProtocol, usecase: MainViewControllerUseCase) { self.dataManager = dataManager + self.usecase = usecase super.init(nibName: nil, bundle: nil) } @@ -96,7 +98,7 @@ final class MainViewController: UIViewController, ConfigurableTableView { } private func setUpTableView() { - configureTableView(todoTableView) + usecase.configureTableView(todoTableView) configureTableView(doingTableView) configureTableView(doneTableView) } @@ -314,7 +316,7 @@ extension MainViewController: UITableViewDelegate { } } -extension MainViewController: AddTodoDelegate, ItemUpdatable { +extension MainViewController: AddTodoDelegate { func didAddTodoItem(title: String, body: String, date: Date) { dataManager.addTodoItem(title: title, body: body, date: date) let newTodoItem = ProjectManager(title: title, body: body, date: date) @@ -325,11 +327,11 @@ extension MainViewController: AddTodoDelegate, ItemUpdatable { func didEditTodoItem(title: String, body: String, date: Date, index: Int) { switch index { case 0.. [ProjectManager] } -extension ItemUpdatable { +final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { guard var mutableItems = items, index >= 0 && index < mutableItems.count else { From a7c1ce40266c021116bc3d657ad9e2c82effa230 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Sat, 30 Sep 2023 16:39:15 +0900 Subject: [PATCH 19/25] =?UTF-8?q?refactor:=20Items=20->=20useCase=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager/App/SceneDelegate.swift | 4 +- .../Controller/MainViewController.swift | 83 +++++++++---------- .../UseCase/MainViewControllerUseCase.swift | 7 ++ 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/ProjectManager/ProjectManager/App/SceneDelegate.swift b/ProjectManager/ProjectManager/App/SceneDelegate.swift index 5474c43ea..7970d0916 100644 --- a/ProjectManager/ProjectManager/App/SceneDelegate.swift +++ b/ProjectManager/ProjectManager/App/SceneDelegate.swift @@ -14,10 +14,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let dataManager: DataManagerProtocol = DataManager() - let usecase: MainViewControllerUseCase = MainViewControllerUseCaseImplementation() + let useCase: MainViewControllerUseCase = MainViewControllerUseCaseImplementation() window = UIWindow(windowScene: windowScene) - let mainViewController = MainViewController(dataManager: dataManager, usecase: usecase) + let mainViewController = MainViewController(dataManager: dataManager, useCase: useCase) let navigationController = UINavigationController(rootViewController: mainViewController) window?.rootViewController = navigationController window?.makeKeyAndVisible() diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 324a8dd94..5451d35e7 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -43,15 +43,12 @@ final class MainViewController: UIViewController, ConfigurableTableView { return stackView }() - private var todoItems = [ProjectManager]() - private var doingItems = [ProjectManager]() - private var doneItems = [ProjectManager]() private let dataManager: DataManagerProtocol - private let usecase: MainViewControllerUseCase + private var useCase: MainViewControllerUseCase - init(dataManager: DataManagerProtocol, usecase: MainViewControllerUseCase) { + init(dataManager: DataManagerProtocol, useCase: MainViewControllerUseCase) { self.dataManager = dataManager - self.usecase = usecase + self.useCase = useCase super.init(nibName: nil, bundle: nil) } @@ -98,7 +95,7 @@ final class MainViewController: UIViewController, ConfigurableTableView { } private func setUpTableView() { - usecase.configureTableView(todoTableView) + configureTableView(todoTableView) configureTableView(doingTableView) configureTableView(doneTableView) } @@ -131,35 +128,35 @@ extension MainViewController: AlertActionCreator { } private func moveToDoing(_ item: ProjectManager) { - if let index = todoItems.firstIndex(where: { $0 == item }) { - todoItems.remove(at: index) - } else if let index = doneItems.firstIndex(where: { $0 == item }) { - doneItems.remove(at: index) + if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { + useCase.todoItems.remove(at: index) + } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { + useCase.doneItems.remove(at: index) } - doingItems.append(item) + useCase.doingItems.append(item) setUpTableViewReloadData() } private func moveToDone(_ item: ProjectManager) { - if let index = todoItems.firstIndex(where: { $0 == item }) { - todoItems.remove(at: index) - } else if let index = doingItems.firstIndex(where: { $0 == item }) { - doingItems.remove(at: index) + if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { + useCase.todoItems.remove(at: index) + } else if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { + useCase.doingItems.remove(at: index) } - doneItems.append(item) + useCase.doneItems.append(item) setUpTableViewReloadData() } private func moveToTodo(_ item: ProjectManager) { - if let index = doingItems.firstIndex(where: { $0 == item }) { - doingItems.remove(at: index) - } else if let index = doneItems.firstIndex(where: { $0 == item }) { - doneItems.remove(at: index) + if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { + useCase.doingItems.remove(at: index) + } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { + useCase.doneItems.remove(at: index) } - todoItems.append(item) + useCase.todoItems.append(item) setUpTableViewReloadData() } @@ -190,11 +187,11 @@ extension MainViewController: AlertActionCreator { let selectedCell: ProjectManager switch (tableView, indexPath.section) { case (todoTableView, 1): - selectedCell = todoItems[indexPath.row] + selectedCell = useCase.todoItems[indexPath.row] case (doingTableView, 1): - selectedCell = doingItems[indexPath.row] + selectedCell = useCase.doingItems[indexPath.row] case (doneTableView, 1): - selectedCell = doneItems[indexPath.row] + selectedCell = useCase.doneItems[indexPath.row] default: return } @@ -240,11 +237,11 @@ extension MainViewController: UITableViewDataSource { case (todoTableView, 0), (doingTableView, 0), (doneTableView, 0): return 1 case (todoTableView, 1): - return todoItems.count + return useCase.todoItems.count case (doingTableView, 1): - return doingItems.count + return useCase.doingItems.count case (doneTableView, 1): - return doneItems.count + return useCase.doneItems.count default: return 0 } @@ -257,29 +254,29 @@ extension MainViewController: UITableViewDataSource { switch (tableView, indexPath.section) { case (todoTableView, 0): - listCell.setModel(title: CellTitleNamespace.todo, count: todoItems.count) + listCell.setModel(title: CellTitleNamespace.todo, count: useCase.todoItems.count) listCell.backgroundColor = .systemGray5 return listCell case (todoTableView, 1): - let todoItem = todoItems[indexPath.row] + let todoItem = useCase.todoItems[indexPath.row] descriptionCell.setModel(title: todoItem.title, body: todoItem.body, date: todoItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell case (doingTableView, 0): - listCell.setModel(title: CellTitleNamespace.doing, count: doingItems.count) + listCell.setModel(title: CellTitleNamespace.doing, count: useCase.doingItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doingTableView, 1): - let doingItem = doingItems[indexPath.row] + let doingItem = useCase.doingItems[indexPath.row] descriptionCell.setModel(title: doingItem.title, body: doingItem.body, date: doingItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell case (doneTableView, 0): - listCell.setModel(title: CellTitleNamespace.done, count: doneItems.count) + listCell.setModel(title: CellTitleNamespace.done, count: useCase.doneItems.count) listCell.backgroundColor = .systemGray5 return listCell case (doneTableView, 1): - let doneItem = doneItems[indexPath.row] + let doneItem = useCase.doneItems[indexPath.row] descriptionCell.setModel(title: doneItem.title, body: doneItem.body, date: doneItem.date) descriptionCell.isUserInteractionEnabled = true return descriptionCell @@ -299,11 +296,11 @@ extension MainViewController: UITableViewDelegate { switch tableView { case todoTableView: - selectedTodoData = todoItems[indexPath.row] + selectedTodoData = useCase.todoItems[indexPath.row] case doingTableView: - selectedTodoData = doingItems[indexPath.row] + selectedTodoData = useCase.doingItems[indexPath.row] case doneTableView: - selectedTodoData = doneItems[indexPath.row] + selectedTodoData = useCase.doneItems[indexPath.row] default: return } @@ -320,18 +317,18 @@ extension MainViewController: AddTodoDelegate { func didAddTodoItem(title: String, body: String, date: Date) { dataManager.addTodoItem(title: title, body: body, date: date) let newTodoItem = ProjectManager(title: title, body: body, date: date) - todoItems.append(newTodoItem) + useCase.todoItems.append(newTodoItem) todoTableView.reloadData() } func didEditTodoItem(title: String, body: String, date: Date, index: Int) { switch index { - case 0.. [ProjectManager] } final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { + var todoItems = [ProjectManager]() + var doingItems = [ProjectManager]() + var doneItems = [ProjectManager]() + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { guard var mutableItems = items, index >= 0 && index < mutableItems.count else { From 985dd48eb5d14e2b263bbe34f70c3a0d9c51a183 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Sat, 30 Sep 2023 22:36:55 +0900 Subject: [PATCH 20/25] =?UTF-8?q?refactor:=20configureTableView=20->=20use?= =?UTF-8?q?Case=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 4 ---- .../Controller/MainViewController.swift | 8 +++---- .../Protocol/ConfigurableTableView.swift | 21 ------------------- .../UseCase/MainViewControllerUseCase.swift | 8 +++++++ 4 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index 504a41404..f580e55cb 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */; }; 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */; }; - 63CC81732AC7FA0200E6355F /* ConfigurableTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -36,7 +35,6 @@ 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellTitleNamespace.swift; sourceTree = ""; }; 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; - 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableTableView.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -126,7 +124,6 @@ isa = PBXGroup; children = ( 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, - 63CC81722AC7FA0200E6355F /* ConfigurableTableView.swift */, ); path = Protocol; sourceTree = ""; @@ -240,7 +237,6 @@ files = ( 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, - 63CC81732AC7FA0200E6355F /* ConfigurableTableView.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index 5451d35e7..dd3746306 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -6,7 +6,7 @@ import UIKit -final class MainViewController: UIViewController, ConfigurableTableView { +final class MainViewController: UIViewController { private let todoTableView: UITableView = { let tableView = UITableView() tableView.translatesAutoresizingMaskIntoConstraints = false @@ -95,9 +95,9 @@ final class MainViewController: UIViewController, ConfigurableTableView { } private func setUpTableView() { - configureTableView(todoTableView) - configureTableView(doingTableView) - configureTableView(doneTableView) + useCase.configureTableView(todoTableView, dataSourceAndDelegate: self) + useCase.configureTableView(doingTableView, dataSourceAndDelegate: self) + useCase.configureTableView(doneTableView, dataSourceAndDelegate: self) } } diff --git a/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift b/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift deleted file mode 100644 index 7627241d7..000000000 --- a/ProjectManager/ProjectManager/Model/Protocol/ConfigurableTableView.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// ConfigurableTableView.swift -// ProjectManager -// -// Created by Hemg on 2023/09/29. -// - -import UIKit - -protocol ConfigurableTableView { - func configureTableView(_ tableView: UITableView) -} - -extension ConfigurableTableView { - func configureTableView(_ tableView: UITableView) { - tableView.dataSource = self as? UITableViewDataSource - tableView.delegate = self as? UITableViewDelegate - tableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) - tableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) - } -} diff --git a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift index 9dc55fe36..e16c502d3 100644 --- a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift +++ b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift @@ -12,6 +12,7 @@ protocol MainViewControllerUseCase { var doingItems: [ProjectManager] { get set } var doneItems: [ProjectManager] { get set } func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] + func configureTableView(_ tableView: UITableView, dataSourceAndDelegate: UITableViewDataSource & UITableViewDelegate) } final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { @@ -19,6 +20,13 @@ final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { var doingItems = [ProjectManager]() var doneItems = [ProjectManager]() + func configureTableView(_ tableView: UITableView, dataSourceAndDelegate: UITableViewDataSource & UITableViewDelegate) { + tableView.dataSource = dataSourceAndDelegate + tableView.delegate = dataSourceAndDelegate + tableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) + tableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) + } + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { guard var mutableItems = items, index >= 0 && index < mutableItems.count else { From 77580b8b8f809f5f9fec43e18ef5d8376f6d3f08 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Sun, 1 Oct 2023 17:06:59 +0900 Subject: [PATCH 21/25] =?UTF-8?q?feat:=20AlertActionCreator=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20=20move=EB=A9=94=EC=84=9C=EB=93=9C=20usecase=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 20 ++---- .../Controller/MainViewController.swift | 69 +++++-------------- .../Model/Entity/TitleItem.swift | 23 +++++++ .../Model/Namespace/AlertNamespace.swift | 12 ---- .../Model/Protocol/AlertActionCreatable.swift | 14 ---- .../UseCase/MainViewControllerUseCase.swift | 33 +++++++++ 6 files changed, 78 insertions(+), 93 deletions(-) create mode 100644 ProjectManager/ProjectManager/Model/Entity/TitleItem.swift delete mode 100644 ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift delete mode 100644 ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index f580e55cb..446c98037 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -13,10 +13,9 @@ 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */; }; - 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; - 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */; }; 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */; }; + 63CC81752AC95D7D00E6355F /* TitleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81742AC95D7D00E6355F /* TitleItem.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -31,10 +30,9 @@ 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifier.swift; sourceTree = ""; }; - 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; - 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellTitleNamespace.swift; sourceTree = ""; }; 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; + 63CC81742AC95D7D00E6355F /* TitleItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleItem.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -86,7 +84,6 @@ 63C5ECBB2AC45243003904C4 /* Model */ = { isa = PBXGroup; children = ( - 63CC81662AC6C1C800E6355F /* Protocol */, 63CC815E2AC6AA3600E6355F /* Namespace */, 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, @@ -98,6 +95,7 @@ isa = PBXGroup; children = ( 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */, + 63CC81742AC95D7D00E6355F /* TitleItem.swift */, ); path = Entity; sourceTree = ""; @@ -114,20 +112,11 @@ isa = PBXGroup; children = ( 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */, - 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */, 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */, ); path = Namespace; sourceTree = ""; }; - 63CC81662AC6C1C800E6355F /* Protocol */ = { - isa = PBXGroup; - children = ( - 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, - ); - path = Protocol; - sourceTree = ""; - }; 63CC816F2AC7F59700E6355F /* UseCase */ = { isa = PBXGroup; children = ( @@ -235,7 +224,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, + 63CC81752AC95D7D00E6355F /* TitleItem.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */, @@ -246,7 +235,6 @@ C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */, 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */, - 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainViewController.swift index dd3746306..6a5a079c2 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainViewController.swift @@ -102,62 +102,29 @@ final class MainViewController: UIViewController { } // MARK: Action -extension MainViewController: AlertActionCreator { +extension MainViewController { private func setUpTableViewReloadData() { todoTableView.reloadData() doingTableView.reloadData() doneTableView.reloadData() } - func createMoveToTodoAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) + private func performMoveToState(_ item: ProjectManager, state: TitleItem) { + switch state { + case .todo: + useCase.moveToTodo(item) + case .doing: + useCase.moveToDoing(item) + case .done: + useCase.moveToDone(item) } - } - - func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - } - - func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - } - - private func moveToDoing(_ item: ProjectManager) { - if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { - useCase.todoItems.remove(at: index) - } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { - useCase.doneItems.remove(at: index) - } - - useCase.doingItems.append(item) - setUpTableViewReloadData() - } - - private func moveToDone(_ item: ProjectManager) { - if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { - useCase.todoItems.remove(at: index) - } else if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { - useCase.doingItems.remove(at: index) - } - - useCase.doneItems.append(item) setUpTableViewReloadData() } - private func moveToTodo(_ item: ProjectManager) { - if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { - useCase.doingItems.remove(at: index) - } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { - useCase.doneItems.remove(at: index) + private func createMoveToStateAction(_ selectedCell: ProjectManager, state: TitleItem) -> UIAlertAction { + return UIAlertAction(title: state.title, style: .default) { [weak self] _ in + self?.performMoveToState(selectedCell, state: state) } - - useCase.todoItems.append(item) - setUpTableViewReloadData() } private func addPressGesture(to tableViews: [UITableView]) { @@ -200,14 +167,14 @@ extension MainViewController: AlertActionCreator { switch tableView { case todoTableView: - alertController.addAction(createMoveToDoingAction(selectedCell)) - alertController.addAction(createMoveToDoneAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .doing)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .done)) case doingTableView: - alertController.addAction(createMoveToTodoAction(selectedCell)) - alertController.addAction(createMoveToDoneAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .todo)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .done)) case doneTableView: - alertController.addAction(createMoveToTodoAction(selectedCell)) - alertController.addAction(createMoveToDoingAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .todo)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .doing)) default: break } diff --git a/ProjectManager/ProjectManager/Model/Entity/TitleItem.swift b/ProjectManager/ProjectManager/Model/Entity/TitleItem.swift new file mode 100644 index 000000000..2b4c8c5c3 --- /dev/null +++ b/ProjectManager/ProjectManager/Model/Entity/TitleItem.swift @@ -0,0 +1,23 @@ +// +// TitleItem.swift +// ProjectManager +// +// Created by Hemg on 2023/10/01. +// + +enum TitleItem { + case todo + case doing + case done + + var title: String { + switch self { + case .todo: + return "Move to TODO" + case .doing: + return "Move to DOING" + case .done: + return "Move to DONE" + } + } +} diff --git a/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift b/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift deleted file mode 100644 index b63e8e103..000000000 --- a/ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// AlertNamespace.swift -// ProjectManager -// -// Created by Hemg on 2023/09/29. -// - -enum AlertNamespace { - static let moveToDoing = "Move to DOING" - static let moveToDone = "Move to DONE" - static let moveToTodo = "Move to TODO" -} diff --git a/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift b/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift deleted file mode 100644 index 0b802daf3..000000000 --- a/ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// AlertActionCreatable.swift -// ProjectManager -// -// Created by Hemg on 2023/09/29. -// - -import UIKit - -protocol AlertActionCreator { - func createMoveToTodoAction(_ selectedCell: ProjectManager) -> UIAlertAction - func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction - func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction -} diff --git a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift index e16c502d3..64335ffd1 100644 --- a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift +++ b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift @@ -13,6 +13,9 @@ protocol MainViewControllerUseCase { var doneItems: [ProjectManager] { get set } func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] func configureTableView(_ tableView: UITableView, dataSourceAndDelegate: UITableViewDataSource & UITableViewDelegate) + func moveToDoing(_ item: ProjectManager) + func moveToDone(_ item: ProjectManager) + func moveToTodo(_ item: ProjectManager) } final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { @@ -40,4 +43,34 @@ final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { return mutableItems } + + func moveToDoing(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + doingItems.append(item) + } + + func moveToDone(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } + + doneItems.append(item) + } + + func moveToTodo(_ item: ProjectManager) { + if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + todoItems.append(item) + } } From 0e2e8271b67ccdbc017d95a1a7edf010f9850d40 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Sun, 1 Oct 2023 17:06:59 +0900 Subject: [PATCH 22/25] =?UTF-8?q?feat:=20MainViewModel=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=A3=BC=EC=9E=85,=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager.xcodeproj/project.pbxproj | 40 +++++---- .../ProjectManager/App/SceneDelegate.swift | 3 +- .../AddTodoViewController.swift | 0 .../{ => MainView}/MainViewController.swift | 85 +++++-------------- .../Controller/MainView/MainViewModel.swift | 34 ++++++++ .../Model/Entity/TitleItem.swift | 23 +++++ .../Model/Namespace/AlertNamespace.swift | 12 --- .../Model/Protocol/AlertActionCreatable.swift | 14 --- .../UseCase/MainViewControllerUseCase.swift | 42 +++++++-- 9 files changed, 139 insertions(+), 114 deletions(-) rename ProjectManager/ProjectManager/Controller/{ => AddTodoView}/AddTodoViewController.swift (100%) rename ProjectManager/ProjectManager/Controller/{ => MainView}/MainViewController.swift (77%) create mode 100644 ProjectManager/ProjectManager/Controller/MainView/MainViewModel.swift create mode 100644 ProjectManager/ProjectManager/Model/Entity/TitleItem.swift delete mode 100644 ProjectManager/ProjectManager/Model/Namespace/AlertNamespace.swift delete mode 100644 ProjectManager/ProjectManager/Model/Protocol/AlertActionCreatable.swift diff --git a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj index f580e55cb..a876db838 100644 --- a/ProjectManager/ProjectManager.xcodeproj/project.pbxproj +++ b/ProjectManager/ProjectManager.xcodeproj/project.pbxproj @@ -13,10 +13,10 @@ 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */; }; 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C5ECCC2AC46F83003904C4 /* DataManager.swift */; }; 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */; }; - 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */; }; - 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */; }; 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */; }; 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */; }; + 63CC81752AC95D7D00E6355F /* TitleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81742AC95D7D00E6355F /* TitleItem.swift */; }; + 63CC81782AC9665900E6355F /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63CC81772AC9665900E6355F /* MainViewModel.swift */; }; C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0525F51E1D0094C4CF /* AppDelegate.swift */; }; C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */; }; C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7431F0925F51E1D0094C4CF /* MainViewController.swift */; }; @@ -31,10 +31,10 @@ 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectManager.swift; sourceTree = ""; }; 63C5ECCC2AC46F83003904C4 /* DataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataManager.swift; sourceTree = ""; }; 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifier.swift; sourceTree = ""; }; - 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertNamespace.swift; sourceTree = ""; }; - 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertActionCreatable.swift; sourceTree = ""; }; 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellTitleNamespace.swift; sourceTree = ""; }; 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; + 63CC81742AC95D7D00E6355F /* TitleItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleItem.swift; sourceTree = ""; }; + 63CC81772AC9665900E6355F /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; C7431F0225F51E1D0094C4CF /* ProjectManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProjectManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7431F0525F51E1D0094C4CF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C7431F0725F51E1D0094C4CF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -67,8 +67,8 @@ 63C5ECB32AC19459003904C4 /* Controller */ = { isa = PBXGroup; children = ( - C7431F0925F51E1D0094C4CF /* MainViewController.swift */, - 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */, + 63CC81762AC9663D00E6355F /* MainView */, + 63CC81792AC9726100E6355F /* AddTodoView */, ); path = Controller; sourceTree = ""; @@ -86,7 +86,6 @@ 63C5ECBB2AC45243003904C4 /* Model */ = { isa = PBXGroup; children = ( - 63CC81662AC6C1C800E6355F /* Protocol */, 63CC815E2AC6AA3600E6355F /* Namespace */, 63C5ECCB2AC46F4E003904C4 /* DataManager */, 63C5ECBE2AC45277003904C4 /* Entity */, @@ -98,6 +97,7 @@ isa = PBXGroup; children = ( 63C5ECC92AC46CDA003904C4 /* ProjectManager.swift */, + 63CC81742AC95D7D00E6355F /* TitleItem.swift */, ); path = Entity; sourceTree = ""; @@ -114,26 +114,34 @@ isa = PBXGroup; children = ( 63CC815F2AC6AA5B00E6355F /* ReuseIdentifier.swift */, - 63CC81612AC6AB8200E6355F /* AlertNamespace.swift */, 63CC816D2AC6D8CA00E6355F /* CellTitleNamespace.swift */, ); path = Namespace; sourceTree = ""; }; - 63CC81662AC6C1C800E6355F /* Protocol */ = { + 63CC816F2AC7F59700E6355F /* UseCase */ = { isa = PBXGroup; children = ( - 63CC81672AC6C1D200E6355F /* AlertActionCreatable.swift */, + 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */, ); - path = Protocol; + path = UseCase; sourceTree = ""; }; - 63CC816F2AC7F59700E6355F /* UseCase */ = { + 63CC81762AC9663D00E6355F /* MainView */ = { isa = PBXGroup; children = ( - 63CC81702AC7F5B600E6355F /* MainViewControllerUseCase.swift */, + C7431F0925F51E1D0094C4CF /* MainViewController.swift */, + 63CC81772AC9665900E6355F /* MainViewModel.swift */, ); - path = UseCase; + path = MainView; + sourceTree = ""; + }; + 63CC81792AC9726100E6355F /* AddTodoView */ = { + isa = PBXGroup; + children = ( + 63C5ECB92AC2FE9A003904C4 /* AddTodoViewController.swift */, + ); + path = AddTodoView; sourceTree = ""; }; C7431EF925F51E1D0094C4CF = { @@ -235,18 +243,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 63CC81682AC6C1D200E6355F /* AlertActionCreatable.swift in Sources */, + 63CC81752AC95D7D00E6355F /* TitleItem.swift in Sources */, 63C5ECCA2AC46CDB003904C4 /* ProjectManager.swift in Sources */, 63C5ECCD2AC46F83003904C4 /* DataManager.swift in Sources */, 63CC816E2AC6D8CA00E6355F /* CellTitleNamespace.swift in Sources */, C7431F0A25F51E1D0094C4CF /* MainViewController.swift in Sources */, + 63CC81782AC9665900E6355F /* MainViewModel.swift in Sources */, 63C5ECB62AC1949A003904C4 /* ListTitleCell.swift in Sources */, 63C5ECBA2AC2FE9A003904C4 /* AddTodoViewController.swift in Sources */, C7431F0625F51E1D0094C4CF /* AppDelegate.swift in Sources */, C7431F0825F51E1D0094C4CF /* SceneDelegate.swift in Sources */, 63CC81602AC6AA5B00E6355F /* ReuseIdentifier.swift in Sources */, 63CC81712AC7F5B600E6355F /* MainViewControllerUseCase.swift in Sources */, - 63CC81622AC6AB8200E6355F /* AlertNamespace.swift in Sources */, 63C5ECB82AC2B957003904C4 /* DescriptionCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ProjectManager/ProjectManager/App/SceneDelegate.swift b/ProjectManager/ProjectManager/App/SceneDelegate.swift index 7970d0916..24edcb5d6 100644 --- a/ProjectManager/ProjectManager/App/SceneDelegate.swift +++ b/ProjectManager/ProjectManager/App/SceneDelegate.swift @@ -15,9 +15,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } let dataManager: DataManagerProtocol = DataManager() let useCase: MainViewControllerUseCase = MainViewControllerUseCaseImplementation() + let viewModel = MainViewModel(useCase: useCase) window = UIWindow(windowScene: windowScene) - let mainViewController = MainViewController(dataManager: dataManager, useCase: useCase) + let mainViewController = MainViewController(dataManager: dataManager, useCase: useCase, viewModel: viewModel) let navigationController = UINavigationController(rootViewController: mainViewController) window?.rootViewController = navigationController window?.makeKeyAndVisible() diff --git a/ProjectManager/ProjectManager/Controller/AddTodoViewController.swift b/ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift similarity index 100% rename from ProjectManager/ProjectManager/Controller/AddTodoViewController.swift rename to ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift diff --git a/ProjectManager/ProjectManager/Controller/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift similarity index 77% rename from ProjectManager/ProjectManager/Controller/MainViewController.swift rename to ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift index dd3746306..ab62739f7 100644 --- a/ProjectManager/ProjectManager/Controller/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift @@ -45,10 +45,12 @@ final class MainViewController: UIViewController { private let dataManager: DataManagerProtocol private var useCase: MainViewControllerUseCase + private let viewModel: MainViewModel - init(dataManager: DataManagerProtocol, useCase: MainViewControllerUseCase) { + init(dataManager: DataManagerProtocol, useCase: MainViewControllerUseCase, viewModel: MainViewModel) { self.dataManager = dataManager self.useCase = useCase + self.viewModel = viewModel super.init(nibName: nil, bundle: nil) } @@ -95,71 +97,27 @@ final class MainViewController: UIViewController { } private func setUpTableView() { - useCase.configureTableView(todoTableView, dataSourceAndDelegate: self) - useCase.configureTableView(doingTableView, dataSourceAndDelegate: self) - useCase.configureTableView(doneTableView, dataSourceAndDelegate: self) + viewModel.configureTableView(todoTableView, dataSourceAndDelegate: self) + viewModel.configureTableView(doingTableView, dataSourceAndDelegate: self) + viewModel.configureTableView(doneTableView, dataSourceAndDelegate: self) } } // MARK: Action -extension MainViewController: AlertActionCreator { +extension MainViewController { private func setUpTableViewReloadData() { todoTableView.reloadData() doingTableView.reloadData() doneTableView.reloadData() } - func createMoveToTodoAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToTodo, style: .default) { [weak self] _ in - self?.moveToTodo(selectedCell) + private func createMoveToStateAction(_ selectedCell: ProjectManager, state: TitleItem) -> UIAlertAction { + return UIAlertAction(title: state.title, style: .default) { [weak self] _ in + self?.viewModel.performMoveToState(selectedCell, state: state) + self?.setUpTableViewReloadData() } } - func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToDoing, style: .default) { [weak self] _ in - self?.moveToDoing(selectedCell) - } - } - - func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction { - return UIAlertAction(title: AlertNamespace.moveToDone, style: .default) { [weak self] _ in - self?.moveToDone(selectedCell) - } - } - - private func moveToDoing(_ item: ProjectManager) { - if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { - useCase.todoItems.remove(at: index) - } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { - useCase.doneItems.remove(at: index) - } - - useCase.doingItems.append(item) - setUpTableViewReloadData() - } - - private func moveToDone(_ item: ProjectManager) { - if let index = useCase.todoItems.firstIndex(where: { $0 == item }) { - useCase.todoItems.remove(at: index) - } else if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { - useCase.doingItems.remove(at: index) - } - - useCase.doneItems.append(item) - setUpTableViewReloadData() - } - - private func moveToTodo(_ item: ProjectManager) { - if let index = useCase.doingItems.firstIndex(where: { $0 == item }) { - useCase.doingItems.remove(at: index) - } else if let index = useCase.doneItems.firstIndex(where: { $0 == item }) { - useCase.doneItems.remove(at: index) - } - - useCase.todoItems.append(item) - setUpTableViewReloadData() - } - private func addPressGesture(to tableViews: [UITableView]) { for tableView in tableViews { let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handlePress(_:))) @@ -200,14 +158,14 @@ extension MainViewController: AlertActionCreator { switch tableView { case todoTableView: - alertController.addAction(createMoveToDoingAction(selectedCell)) - alertController.addAction(createMoveToDoneAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .doing)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .done)) case doingTableView: - alertController.addAction(createMoveToTodoAction(selectedCell)) - alertController.addAction(createMoveToDoneAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .todo)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .done)) case doneTableView: - alertController.addAction(createMoveToTodoAction(selectedCell)) - alertController.addAction(createMoveToDoingAction(selectedCell)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .todo)) + alertController.addAction(createMoveToStateAction(selectedCell, state: .doing)) default: break } @@ -324,11 +282,14 @@ extension MainViewController: AddTodoDelegate { func didEditTodoItem(title: String, body: String, date: Date, index: Int) { switch index { case 0.. UIAlertAction - func createMoveToDoingAction(_ selectedCell: ProjectManager) -> UIAlertAction - func createMoveToDoneAction(_ selectedCell: ProjectManager) -> UIAlertAction -} diff --git a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift index e16c502d3..29ebd80a9 100644 --- a/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift +++ b/ProjectManager/ProjectManager/UseCase/MainViewControllerUseCase.swift @@ -11,8 +11,10 @@ protocol MainViewControllerUseCase { var todoItems: [ProjectManager] { get set } var doingItems: [ProjectManager] { get set } var doneItems: [ProjectManager] { get set } - func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] - func configureTableView(_ tableView: UITableView, dataSourceAndDelegate: UITableViewDataSource & UITableViewDelegate) + func moveToDoing(_ item: ProjectManager) + func moveToDone(_ item: ProjectManager) + func moveToTodo(_ item: ProjectManager) + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int) -> [ProjectManager] } final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { @@ -20,14 +22,37 @@ final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { var doingItems = [ProjectManager]() var doneItems = [ProjectManager]() - func configureTableView(_ tableView: UITableView, dataSourceAndDelegate: UITableViewDataSource & UITableViewDelegate) { - tableView.dataSource = dataSourceAndDelegate - tableView.delegate = dataSourceAndDelegate - tableView.register(ListTitleCell.self, forCellReuseIdentifier: ReuseIdentifier.listTitleCell) - tableView.register(DescriptionCell.self, forCellReuseIdentifier: ReuseIdentifier.descriptionCell) + func moveToDoing(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + doingItems.append(item) + } + + func moveToDone(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } else if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } + + doneItems.append(item) + } + + func moveToTodo(_ item: ProjectManager) { + if let index = doingItems.firstIndex(where: { $0 == item }) { + doingItems.remove(at: index) + } else if let index = doneItems.firstIndex(where: { $0 == item }) { + doneItems.remove(at: index) + } + + todoItems.append(item) } - func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int, tableView: UITableView) -> [ProjectManager] { + func updateItems(_ items: [ProjectManager]?, title: String, body: String, date: Date, index: Int) -> [ProjectManager] { guard var mutableItems = items, index >= 0 && index < mutableItems.count else { return items ?? [] @@ -36,7 +61,6 @@ final class MainViewControllerUseCaseImplementation: MainViewControllerUseCase { mutableItems[index].title = title mutableItems[index].body = body mutableItems[index].date = date - tableView.reloadData() return mutableItems } From 8b656888e0aa407c95d2e48e1f296592b60e104c Mon Sep 17 00:00:00 2001 From: hemg2 Date: Mon, 2 Oct 2023 15:49:25 +0900 Subject: [PATCH 23/25] =?UTF-8?q?feat:=20SwipeAction=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MainView/MainViewController.swift | 28 +++++++++++++++++++ .../Model/DataManager/DataManager.swift | 7 +++++ 2 files changed, 35 insertions(+) diff --git a/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift index ab62739f7..1545b4037 100644 --- a/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift @@ -269,6 +269,34 @@ extension MainViewController: UITableViewDelegate { addTodoView.delegate = self present(navigationController, animated: true) } + + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let delete = UIContextualAction(style: .normal, title: "Delete") { [weak self] (_, _, completionHandler) in + guard let self else { return } + guard indexPath.section == 1 else { return } + var deletedItem: ProjectManager? + switch tableView { + case self.todoTableView: + deletedItem = self.useCase.todoItems.remove(at: indexPath.row) + case self.doingTableView: + deletedItem = self.useCase.doingItems.remove(at: indexPath.row) + case self.doneTableView: + deletedItem = self.useCase.doneItems.remove(at: indexPath.row) + default: + return + } + + guard let deletedItem = deletedItem else { return } + self.dataManager.deleteTodoItem(deletedItem) + tableView.reloadData() + completionHandler(true) + } + + delete.backgroundColor = .systemRed + delete.image = UIImage(systemName: "trash.fill") + + return UISwipeActionsConfiguration(actions: [delete]) + } } extension MainViewController: AddTodoDelegate { diff --git a/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift index f415edab0..a5562f877 100644 --- a/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift +++ b/ProjectManager/ProjectManager/Model/DataManager/DataManager.swift @@ -9,6 +9,7 @@ import Foundation protocol DataManagerProtocol { func addTodoItem(title: String, body: String, date: Date) + func deleteTodoItem(_ item: ProjectManager) } final class DataManager: DataManagerProtocol { @@ -18,4 +19,10 @@ final class DataManager: DataManagerProtocol { let newItem = ProjectManager(title: title, body: body, date: date) todoItems.append(newItem) } + + func deleteTodoItem(_ item: ProjectManager) { + if let index = todoItems.firstIndex(where: { $0 == item }) { + todoItems.remove(at: index) + } + } } From 6d7bd96e70e13a537d52844872791c0e977b50e4 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Tue, 3 Oct 2023 15:11:06 +0900 Subject: [PATCH 24/25] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controller/AddTodoView/AddTodoViewController.swift | 7 ++----- .../Controller/MainView/MainViewController.swift | 10 ++++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift b/ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift index 7717fff8e..439752c19 100644 --- a/ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift +++ b/ProjectManager/ProjectManager/Controller/AddTodoView/AddTodoViewController.swift @@ -47,19 +47,16 @@ final class AddTodoViewController: UIViewController { weak var delegate: AddTodoDelegate? private var todoItems: ProjectManager? - private let dataManager: DataManagerProtocol private var isNew: Bool - init(dataManager: DataManagerProtocol) { - self.dataManager = dataManager + init() { self.isNew = true super.init(nibName: nil, bundle: nil) } - init(todoItems: ProjectManager?, dataManager: DataManagerProtocol) { + init(todoItems: ProjectManager?) { self.isNew = false self.todoItems = todoItems - self.dataManager = dataManager super.init(nibName: nil, bundle: nil) } diff --git a/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift index 1545b4037..266f0fb9b 100644 --- a/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift +++ b/ProjectManager/ProjectManager/Controller/MainView/MainViewController.swift @@ -127,7 +127,7 @@ extension MainViewController { } @objc private func addButton() { - let addTODOView = AddTodoViewController(dataManager: dataManager) + let addTODOView = AddTodoViewController() let navigationController = UINavigationController(rootViewController: addTODOView) let backgroundView = UIView(frame: view.bounds) backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.5) @@ -263,7 +263,7 @@ extension MainViewController: UITableViewDelegate { return } - let addTodoView = AddTodoViewController(todoItems: selectedTodoData, dataManager: dataManager) + let addTodoView = AddTodoViewController(todoItems: selectedTodoData) let navigationController = UINavigationController(rootViewController: addTodoView) addTodoView.delegate = self @@ -315,9 +315,11 @@ extension MainViewController: AddTodoDelegate { case 0.. Date: Thu, 5 Oct 2023 19:40:15 +0900 Subject: [PATCH 25/25] =?UTF-8?q?refactor:=20countLabel=20background?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProjectManager/View/DescriptionCell.swift | 1 + .../ProjectManager/View/ListTitleCell.swift | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ProjectManager/ProjectManager/View/DescriptionCell.swift b/ProjectManager/ProjectManager/View/DescriptionCell.swift index b6f7b3e98..29503ca2a 100644 --- a/ProjectManager/ProjectManager/View/DescriptionCell.swift +++ b/ProjectManager/ProjectManager/View/DescriptionCell.swift @@ -20,6 +20,7 @@ final class DescriptionCell: UITableViewCell { let label = UILabel() label.font = .preferredFont(forTextStyle: .body) label.translatesAutoresizingMaskIntoConstraints = false + label.numberOfLines = 3 return label }() diff --git a/ProjectManager/ProjectManager/View/ListTitleCell.swift b/ProjectManager/ProjectManager/View/ListTitleCell.swift index a0e8fc313..cbe98f1d4 100644 --- a/ProjectManager/ProjectManager/View/ListTitleCell.swift +++ b/ProjectManager/ProjectManager/View/ListTitleCell.swift @@ -21,7 +21,9 @@ final class ListTitleCell: UITableViewCell { let label = UILabel() label.font = .preferredFont(forTextStyle: .callout) label.translatesAutoresizingMaskIntoConstraints = false - label.numberOfLines = 3 + label.backgroundColor = .black + label.textColor = .white + label.textAlignment = .center return label }() @@ -50,13 +52,21 @@ final class ListTitleCell: UITableViewCell { NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 4), - titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 4), + titleLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4), - countLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 4), - countLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor) + countLabel.leadingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 8), + countLabel.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor), + countLabel.widthAnchor.constraint(equalToConstant: 22.5), + countLabel.heightAnchor.constraint(equalToConstant: 22.5) ]) } + override func layoutSubviews() { + super.layoutSubviews() + countLabel.layer.cornerRadius = countLabel.bounds.width / 2 + countLabel.clipsToBounds = true + } + func setModel(title: String, count: Int) { titleLabel.text = title countLabel.text = String(count)