From f14e2959ce26a7b68158a94934f88d794096188b Mon Sep 17 00:00:00 2001 From: Serena Date: Mon, 11 Sep 2023 21:38:07 +0900 Subject: [PATCH 01/34] =?UTF-8?q?feat:=20CoreData=EA=B3=BC=20DiaryCoreData?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20CRUD=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 26 ++++++- .../xcshareddata/xcschemes/Diary.xcscheme | 77 +++++++++++++++++++ Diary/App/AppDelegate.swift | 51 +----------- Diary/App/SceneDelegate.swift | 6 -- .../Diary.xcdatamodel/contents | 8 ++ Diary/Manager/CoreDataManager.swift | 47 +++++++++++ Diary/Manager/DiaryCoreDataManager.swift | 16 ++++ .../Diary.xcdatamodeld/.xccurrentversion | 0 .../Diary.xcdatamodel/contents | 8 ++ .../CoreData/DiaryEntity+CoreDataClass.swift | 15 ++++ .../DiaryEntity+CoreDataProperties.swift | 27 +++++++ .../Diary.xcdatamodel/contents | 4 - 12 files changed, 224 insertions(+), 61 deletions(-) create mode 100644 Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme create mode 100644 Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents create mode 100644 Diary/Manager/CoreDataManager.swift create mode 100644 Diary/Manager/DiaryCoreDataManager.swift rename Diary/Model/{ => CoreData}/Diary.xcdatamodeld/.xccurrentversion (100%) create mode 100644 Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents create mode 100644 Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift create mode 100644 Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift delete mode 100644 Diary/Model/Diary.xcdatamodeld/Diary.xcdatamodel/contents diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 3baf42a20..19d9a227e 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -16,6 +16,10 @@ C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */; }; C739AE31284DF28600741E8F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C739AE30284DF28600741E8F /* Assets.xcassets */; }; C739AE34284DF28600741E8F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C739AE32284DF28600741E8F /* LaunchScreen.storyboard */; }; + D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */; }; + D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */; }; + D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; + D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */; }; D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */; }; D2C1FBF32A9F0A0900526DA5 /* AddDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* AddDiaryViewController.swift */; }; D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */; }; @@ -34,6 +38,10 @@ C739AE30284DF28600741E8F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C739AE33284DF28600741E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C739AE35284DF28600741E8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; + D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; + D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; + D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryCoreDataManager.swift; sourceTree = ""; }; D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContent.swift; sourceTree = ""; }; D2C1FBF22A9F0A0900526DA5 /* AddDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddDiaryViewController.swift; sourceTree = ""; }; D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = ""; }; @@ -81,7 +89,7 @@ 5BBC44362A9F025500C528DD /* Model */ = { isa = PBXGroup; children = ( - C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, + D2BCA2B22AAF3A8700D55F4C /* CoreData */, D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */, 5BBC443A2A9F276100C528DD /* DiarySample.swift */, ); @@ -128,10 +136,22 @@ path = Diary; sourceTree = ""; }; + D2BCA2B22AAF3A8700D55F4C /* CoreData */ = { + isa = PBXGroup; + children = ( + C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, + D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */, + D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */, + ); + path = CoreData; + sourceTree = ""; + }; D2C1FBF42A9F1EA400526DA5 /* Manager */ = { isa = PBXGroup; children = ( D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */, + D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */, + D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */, ); path = Manager; sourceTree = ""; @@ -241,10 +261,14 @@ C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, D2C1FBF32A9F0A0900526DA5 /* AddDiaryViewController.swift in Sources */, + D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */, D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, + D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, + D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */, + D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */, 5BBC443B2A9F276100C528DD /* DiarySample.swift in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, ); diff --git a/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme b/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme new file mode 100644 index 000000000..90943b4f2 --- /dev/null +++ b/Diary.xcodeproj/xcshareddata/xcschemes/Diary.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Diary/App/AppDelegate.swift b/Diary/App/AppDelegate.swift index 4614bc7fb..645027cad 100644 --- a/Diary/App/AppDelegate.swift +++ b/Diary/App/AppDelegate.swift @@ -9,16 +9,12 @@ import CoreData @main class AppDelegate: UIResponder, UIApplicationDelegate { - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - + // MARK: UISceneSession Lifecycle - func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. @@ -30,49 +26,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - - // MARK: - Core Data stack - - lazy var persistentContainer: NSPersistentContainer = { - /* - The persistent container for the application. This implementation - creates and returns a container, having loaded the store for the - application to it. This property is optional since there are legitimate - error conditions that could cause the creation of the store to fail. - */ - let container = NSPersistentContainer(name: "Diary") - container.loadPersistentStores(completionHandler: { (storeDescription, error) in - if let error = error as NSError? { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - - /* - Typical reasons for an error here include: - * The parent directory does not exist, cannot be created, or disallows writing. - * The persistent store is not accessible, due to permissions or data protection when the device is locked. - * The device is out of space. - * The store could not be migrated to the current model version. - Check the error message to determine what the actual problem was. - */ - fatalError("Unresolved error \(error), \(error.userInfo)") - } - }) - return container - }() - - // MARK: - Core Data Saving support - - func saveContext () { - let context = persistentContainer.viewContext - if context.hasChanges { - do { - try context.save() - } catch { - // Replace this implementation with code to handle the error appropriately. - // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. - let nserror = error as NSError - fatalError("Unresolved error \(nserror), \(nserror.userInfo)") - } - } - } } diff --git a/Diary/App/SceneDelegate.swift b/Diary/App/SceneDelegate.swift index 94a3163d3..90e3e9f91 100644 --- a/Diary/App/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -45,11 +45,5 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } func sceneDidEnterBackground(_ scene: UIScene) { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state information - // to restore the scene back to its current state. - - // Save changes in the application's managed object context when the application transitions to the background. - (UIApplication.shared.delegate as? AppDelegate)?.saveContext() } } diff --git a/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents new file mode 100644 index 000000000..ff04e6f8c --- /dev/null +++ b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift new file mode 100644 index 000000000..415d19edd --- /dev/null +++ b/Diary/Manager/CoreDataManager.swift @@ -0,0 +1,47 @@ +// +// CoreDataManager.swift +// Diary +// +// Created by Zion, Serena on 2023/09/11. +// + +import CoreData + +class CoreDataManager { + private let name: String + lazy var context = persistentContainer.viewContext + + private lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: name) + + container.loadPersistentStores(completionHandler: { _, _ in }) + return container + }() + + init(name: String) { + self.name = name + } + + func fetchData(request: NSFetchRequest) throws -> [T] { + let data = try context.fetch(request) + + return data + } + + func deleteData(entity: NSManagedObject) { + context.delete(entity) + } + + 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/Diary/Manager/DiaryCoreDataManager.swift b/Diary/Manager/DiaryCoreDataManager.swift new file mode 100644 index 000000000..073f7c29e --- /dev/null +++ b/Diary/Manager/DiaryCoreDataManager.swift @@ -0,0 +1,16 @@ +// +// DiaryCoreDataManager.swift +// Diary +// +// Created by Zion, Serena on 2023/09/11. +// + +final class DiaryCoreDataManager: CoreDataManager { + func createDiaryData(title: String, body: String, date: Double) { + let entity = DiaryEntity(context: context) + + entity.title = title + entity.body = body + entity.date = date + } +} diff --git a/Diary/Model/Diary.xcdatamodeld/.xccurrentversion b/Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion similarity index 100% rename from Diary/Model/Diary.xcdatamodeld/.xccurrentversion rename to Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion diff --git a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents new file mode 100644 index 000000000..1c3d18eb2 --- /dev/null +++ b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift new file mode 100644 index 000000000..1a2cc132a --- /dev/null +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// DiaryEntity+CoreDataClass.swift +// Diary +// +// Created by Hyun A Song on 2023/09/11. +// +// + +import Foundation +import CoreData + +@objc(DiaryEntity) +public class DiaryEntity: NSManagedObject { + +} diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift new file mode 100644 index 000000000..22e67af6f --- /dev/null +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift @@ -0,0 +1,27 @@ +// +// DiaryEntity+CoreDataProperties.swift +// Diary +// +// Created by Hyun A Song on 2023/09/11. +// +// + +import Foundation +import CoreData + + +extension DiaryEntity { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "DiaryEntity") + } + + @NSManaged public var date: Double + @NSManaged public var body: String? + @NSManaged public var title: String? + +} + +extension DiaryEntity : Identifiable { + +} diff --git a/Diary/Model/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Model/Diary.xcdatamodeld/Diary.xcdatamodel/contents deleted file mode 100644 index 50d2514e8..000000000 --- a/Diary/Model/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From f586ac68684a94532696045c696de4acfd0608eb Mon Sep 17 00:00:00 2001 From: Zion Date: Mon, 11 Sep 2023 21:45:56 +0900 Subject: [PATCH 02/34] =?UTF-8?q?feat:=20ActivityViewControllerShowable,?= =?UTF-8?q?=20AlertControllerShowable=20=ED=83=80=EC=9E=85=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 8 +++++ .../ActivityViewControllerShowable.swift | 20 +++++++++++++ Diary/Protocol/AlertControllerShowable.swift | 30 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 Diary/Protocol/ActivityViewControllerShowable.swift create mode 100644 Diary/Protocol/AlertControllerShowable.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 19d9a227e..f68f9deb3 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */; }; 5BBC443B2A9F276100C528DD /* DiarySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC443A2A9F276100C528DD /* DiarySample.swift */; }; 5BBC443D2A9F30ED00C528DD /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */; }; + 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */; }; + 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */; }; C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE24284DF28600741E8F /* AppDelegate.swift */; }; C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE26284DF28600741E8F /* SceneDelegate.swift */; }; C739AE29284DF28600741E8F /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* MainViewController.swift */; }; @@ -30,6 +32,8 @@ 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTableViewCell.swift; sourceTree = ""; }; 5BBC443A2A9F276100C528DD /* DiarySample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiarySample.swift; sourceTree = ""; }; 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; + 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertControllerShowable.swift; sourceTree = ""; }; + 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityViewControllerShowable.swift; sourceTree = ""; }; C739AE21284DF28600741E8F /* Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diary.app; sourceTree = BUILT_PRODUCTS_DIR; }; C739AE24284DF28600741E8F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C739AE26284DF28600741E8F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -160,6 +164,8 @@ isa = PBXGroup; children = ( D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */, + 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */, + 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */, ); path = Protocol; sourceTree = ""; @@ -257,6 +263,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */, + 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */, C739AE29284DF28600741E8F /* MainViewController.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, diff --git a/Diary/Protocol/ActivityViewControllerShowable.swift b/Diary/Protocol/ActivityViewControllerShowable.swift new file mode 100644 index 000000000..d8a7b0390 --- /dev/null +++ b/Diary/Protocol/ActivityViewControllerShowable.swift @@ -0,0 +1,20 @@ +// +// ActivityViewControllerShowable.swift +// Diary +// +// Created by Hyungmin Lee on 2023/09/11. +// + +import UIKit + +protocol ActivityViewControllerShowable where Self: UIViewController { + func showActivityViewController(items: [Any]) +} + +extension ActivityViewControllerShowable { + func showActivityViewController(items: [Any]) { + let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) + + present(activityViewController, animated: true) + } +} diff --git a/Diary/Protocol/AlertControllerShowable.swift b/Diary/Protocol/AlertControllerShowable.swift new file mode 100644 index 000000000..bc8a0e807 --- /dev/null +++ b/Diary/Protocol/AlertControllerShowable.swift @@ -0,0 +1,30 @@ +// +// AlertControllerShowable.swift +// Diary +// +// Created by Zion, Serena on 2023/09/11. +// + +import UIKit + +protocol AlertControllerShowable where Self: UIViewController { + func showAlertController(title: String?, + message: String?, + style: UIAlertController.Style, + actions: [UIAlertAction]) +} + +extension AlertControllerShowable { + func showAlertController(title: String? = nil, + message: String? = nil, + style: UIAlertController.Style = .actionSheet, + actions: [UIAlertAction]) { + let alertController = UIAlertController(title: title, message: message, preferredStyle: style) + + actions.forEach { + alertController.addAction($0) + } + + present(alertController, animated: true) + } +} From 8536d5cd92a4d0dc5a7b53bc24203ff80762ea4e Mon Sep 17 00:00:00 2001 From: Zion Date: Mon, 11 Sep 2023 22:00:02 +0900 Subject: [PATCH 03/34] =?UTF-8?q?feat:=20ViewController=EC=97=90=20Showabl?= =?UTF-8?q?e=20Type=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 8 ++--- ....swift => DiaryDetailViewController.swift} | 32 +++++++++++++++-- Diary/Controller/MainViewController.swift | 35 +++++++++++++++++-- Diary/Manager/AppManager.swift | 2 +- .../ActivityViewControllerShowable.swift | 2 +- 5 files changed, 69 insertions(+), 10 deletions(-) rename Diary/Controller/{AddDiaryViewController.swift => DiaryDetailViewController.swift} (56%) diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index f68f9deb3..8c9c9832b 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -23,7 +23,7 @@ D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */; }; D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */; }; - D2C1FBF32A9F0A0900526DA5 /* AddDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* AddDiaryViewController.swift */; }; + D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */; }; D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */; }; D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */; }; /* End PBXBuildFile section */ @@ -47,7 +47,7 @@ D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryCoreDataManager.swift; sourceTree = ""; }; D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContent.swift; sourceTree = ""; }; - D2C1FBF22A9F0A0900526DA5 /* AddDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddDiaryViewController.swift; sourceTree = ""; }; + D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = ""; }; D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifiable.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -76,7 +76,7 @@ isa = PBXGroup; children = ( C739AE28284DF28600741E8F /* MainViewController.swift */, - D2C1FBF22A9F0A0900526DA5 /* AddDiaryViewController.swift */, + D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */, ); path = Controller; sourceTree = ""; @@ -268,7 +268,7 @@ C739AE29284DF28600741E8F /* MainViewController.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, - D2C1FBF32A9F0A0900526DA5 /* AddDiaryViewController.swift in Sources */, + D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */, D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */, D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, diff --git a/Diary/Controller/AddDiaryViewController.swift b/Diary/Controller/DiaryDetailViewController.swift similarity index 56% rename from Diary/Controller/AddDiaryViewController.swift rename to Diary/Controller/DiaryDetailViewController.swift index 53c014fb7..0feda7775 100644 --- a/Diary/Controller/AddDiaryViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -1,5 +1,5 @@ // -// AddDiaryViewController.swift +// DiaryDetailViewController.swift // Diary // // Created by Zion, Serena on 2023/08/30. @@ -7,7 +7,7 @@ import UIKit -final class AddDiaryViewController: UIViewController { +final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { private lazy var textView: UITextView = { let textView = UITextView() @@ -56,5 +56,33 @@ final class AddDiaryViewController: UIViewController { private func setUpViewController() { view.backgroundColor = .systemBackground navigationItem.title = todayDate + navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) + } +} + +// MARK: - Button Action +extension DiaryDetailViewController { + @objc + func didTappedMoreButton() { + let shareAction = UIAlertAction(title: "Share...", style: .default) { _ in + self.showActivityViewController(items: [""]) + } + + let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { _ in + self.didTappedDeleteAction() + } + + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) + + showAlertController(actions: [shareAction, deleteAction, cancelAction]) + } + + private func didTappedDeleteAction() { + let cancelAction = UIAlertAction(title: "취소", style: .cancel) + let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in + + } + + showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) } } diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index dc7464ba4..173ed3f30 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -10,7 +10,7 @@ protocol MainViewControllerDelegate: AnyObject { func didTappedRightAddButton() } -final class MainViewController: UIViewController { +final class MainViewController: UIViewController, AlertControllerShowable { enum Section { case main } @@ -20,9 +20,10 @@ final class MainViewController: UIViewController { private let dateFormatter: DateFormatter private var diffableDatasource: UITableViewDiffableDataSource? - private let tableView: UITableView = { + private lazy var tableView: UITableView = { let tableView = UITableView() + tableView.delegate = self tableView.allowsSelection = false tableView.register(MainTableViewCell.self, forCellReuseIdentifier: MainTableViewCell.indentifier) tableView.translatesAutoresizingMaskIntoConstraints = false @@ -70,6 +71,24 @@ final class MainViewController: UIViewController { } } +// MARK: - TableView Delegate +extension MainViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { + let shareAction: UIContextualAction = .init(style: .normal, title: "Share") { _, _, _ in + + } + + let deleteAction: UIContextualAction = .init(style: .destructive, title: "Delete") { _, _, _ in + self.didTappedDeleteAction() + } + + let swipeActionConfiguration: UISwipeActionsConfiguration = .init(actions: [deleteAction, shareAction]) + + swipeActionConfiguration.performsFirstActionWithFullSwipe = true + return swipeActionConfiguration + } +} + // MARK: - TableViewDiffableDataSource extension MainViewController { private func setUpTableViewDiffableDataSource() { @@ -99,4 +118,16 @@ extension MainViewController { private func didTappedRightAddButton() { delegate?.didTappedRightAddButton() } + + private func didTappedDeleteAction() { + let cancelAction = UIAlertAction(title: "취소", style: .cancel) + let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in + + } + + showAlertController(title: "진짜요?", + message: "정말로 삭제하시겠어요?", + style: .alert, + actions: [cancelAction, deleteAction]) + } } diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index a9be3e07a..b21968a06 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -46,7 +46,7 @@ extension AppManager: MainViewControllerDelegate { func didTappedRightAddButton() { let diarySample = DiarySample() let todayDate = dateFormatter.string(from: Date()) - let addDiaryViewController = AddDiaryViewController(todayDate: todayDate, + let addDiaryViewController = DiaryDetailViewController(todayDate: todayDate, diaryTitle: diarySample.title, diaryDescription: diarySample.description) diff --git a/Diary/Protocol/ActivityViewControllerShowable.swift b/Diary/Protocol/ActivityViewControllerShowable.swift index d8a7b0390..ed6e6a2f3 100644 --- a/Diary/Protocol/ActivityViewControllerShowable.swift +++ b/Diary/Protocol/ActivityViewControllerShowable.swift @@ -2,7 +2,7 @@ // ActivityViewControllerShowable.swift // Diary // -// Created by Hyungmin Lee on 2023/09/11. +// Created by Zion, Serena on 2023/09/11. // import UIKit From 359557c7c32f94a8bcb8dc2f131ada4ede0f9b59 Mon Sep 17 00:00:00 2001 From: Serena Date: Mon, 11 Sep 2023 22:44:02 +0900 Subject: [PATCH 04/34] =?UTF-8?q?refactor:=20AppManager=EC=97=90=20DiaryDa?= =?UTF-8?q?taManager=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/App/SceneDelegate.swift | 3 ++- Diary/Manager/AppManager.swift | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Diary/App/SceneDelegate.swift b/Diary/App/SceneDelegate.swift index 90e3e9f91..b7b791a59 100644 --- a/Diary/App/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -14,8 +14,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } let navigationController = UINavigationController() - appManager = AppManager(navigationController: navigationController) + let diaryDataManager = DiaryCoreDataManager(name: "Diary") + appManager = AppManager(navigationController: navigationController, diaryDataManager: diaryDataManager) appManager?.start() window = UIWindow(windowScene: windowScene) window?.rootViewController = navigationController diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index b21968a06..e9e9b770b 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -20,8 +20,11 @@ final class AppManager { return dateFormatter }() - init(navigationController: UINavigationController) { + private let diaryDataManager: DiaryCoreDataManager + + init(navigationController: UINavigationController, diaryDataManager: DiaryCoreDataManager) { self.navigationController = navigationController + self.diaryDataManager = diaryDataManager } func start() { From 165c3386d272c1c236377bba74ade9357945e271 Mon Sep 17 00:00:00 2001 From: Serena Date: Mon, 11 Sep 2023 22:45:27 +0900 Subject: [PATCH 05/34] =?UTF-8?q?refactor:=20DiarySample=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20DiaryEntity=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DiaryDetailViewController.swift | 18 ++++++++--------- Diary/Controller/MainViewController.swift | 20 ++++++++++--------- Diary/Manager/AppManager.swift | 12 ++--------- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 0feda7775..a57d95615 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -8,22 +8,17 @@ import UIKit final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { - private lazy var textView: UITextView = { + private let textView: UITextView = { let textView = UITextView() - textView.text = diaryTitle + "\n\n" + diaryDescription textView.translatesAutoresizingMaskIntoConstraints = false return textView }() - private let todayDate: String - private let diaryTitle: String - private let diaryDescription: String + private var diaryEntity: DiaryEntity? - init(todayDate: String, diaryTitle: String, diaryDescription: String) { - self.todayDate = todayDate - self.diaryTitle = diaryTitle - self.diaryDescription = diaryDescription + init(diaryEntity: DiaryEntity? = nil) { + self.diaryEntity = diaryEntity super.init(nibName: nil, bundle: nil) } @@ -40,6 +35,10 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable setUpViewController() } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + } + private func configureUI() { view.addSubview(textView) } @@ -55,7 +54,6 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable private func setUpViewController() { view.backgroundColor = .systemBackground - navigationItem.title = todayDate navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) } } diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index 173ed3f30..e5c3a6cb8 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -16,9 +16,9 @@ final class MainViewController: UIViewController, AlertControllerShowable { } weak var delegate: MainViewControllerDelegate? - private let diaryContents: [DiaryContent] + private let diaryEntity: [DiaryEntity] private let dateFormatter: DateFormatter - private var diffableDatasource: UITableViewDiffableDataSource? + private var diffableDatasource: UITableViewDiffableDataSource? private lazy var tableView: UITableView = { let tableView = UITableView() @@ -30,8 +30,8 @@ final class MainViewController: UIViewController, AlertControllerShowable { return tableView }() - init(diaryContents: [DiaryContent], dateFormatter: DateFormatter) { - self.diaryContents = diaryContents + init(diaryEntity: [DiaryEntity], dateFormatter: DateFormatter) { + self.diaryEntity = diaryEntity self.dateFormatter = dateFormatter super.init(nibName: nil, bundle: nil) @@ -92,22 +92,23 @@ extension MainViewController: UITableViewDelegate { // MARK: - TableViewDiffableDataSource extension MainViewController { private func setUpTableViewDiffableDataSource() { - diffableDatasource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, diarySample in + diffableDatasource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, diaryEntity in guard let self = self, let cell = tableView.dequeueReusableCell(withIdentifier: MainTableViewCell.indentifier, for: indexPath) as? MainTableViewCell else { return UITableViewCell() } - let date = Date(timeIntervalSince1970: diarySample.date) + let date = Date(timeIntervalSince1970: diaryEntity.date) let formattedDate = self.dateFormatter.string(from: date) - cell.setUpContents(title: diarySample.title, date: formattedDate, body: diarySample.body) + + cell.setUpContents(title: diaryEntity.title, date: formattedDate, body: diaryEntity.body) return cell }) } private func setUpTableViewDiffableDataSourceSnapShot() { - var snapShot = NSDiffableDataSourceSnapshot() + var snapShot = NSDiffableDataSourceSnapshot() snapShot.appendSections([.main]) - snapShot.appendItems(diaryContents) + snapShot.appendItems(diaryEntity) diffableDatasource?.apply(snapShot) } } @@ -117,6 +118,7 @@ extension MainViewController { @objc private func didTappedRightAddButton() { delegate?.didTappedRightAddButton() + } private func didTappedDeleteAction() { diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index e9e9b770b..5913c6600 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -28,20 +28,12 @@ final class AppManager { } func start() { - guard let dairyContents = decodeDairySample(fileName: "sample") else { return } - let mainViewController = MainViewController(diaryContents: dairyContents, dateFormatter: dateFormatter) + guard let diaryData = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } + let mainViewController = MainViewController(diaryEntity: diaryData, dateFormatter: dateFormatter) mainViewController.delegate = self navigationController.viewControllers = [mainViewController] } - - private func decodeDairySample(fileName: String) -> [DiaryContent]? { - let jsonDecoder = JSONDecoder() - guard let asset = NSDataAsset(name: fileName) else { return nil } - guard let data = try? jsonDecoder.decode([DiaryContent].self, from: asset.data) else { return nil } - - return data - } } // MARK: - MainViewControllerDelegate From 0759a83b9483495fd9244d3d50fd885c8f46d9ac Mon Sep 17 00:00:00 2001 From: Serena Date: Mon, 11 Sep 2023 22:45:54 +0900 Subject: [PATCH 06/34] =?UTF-8?q?refactor:=20DiaryEntity=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift index 22e67af6f..9374b2e30 100644 --- a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift @@ -17,11 +17,11 @@ extension DiaryEntity { } @NSManaged public var date: Double - @NSManaged public var body: String? - @NSManaged public var title: String? + @NSManaged public var body: String + @NSManaged public var title: String } -extension DiaryEntity : Identifiable { +extension DiaryEntity: Identifiable { } From 8195eefb5a7b1b13705dc30706450d85d37d730f Mon Sep 17 00:00:00 2001 From: Serena Date: Mon, 11 Sep 2023 22:49:17 +0900 Subject: [PATCH 07/34] =?UTF-8?q?refactor:=20DiaryDetailViewController=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/AppManager.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 5913c6600..2db526a19 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -41,9 +41,7 @@ extension AppManager: MainViewControllerDelegate { func didTappedRightAddButton() { let diarySample = DiarySample() let todayDate = dateFormatter.string(from: Date()) - let addDiaryViewController = DiaryDetailViewController(todayDate: todayDate, - diaryTitle: diarySample.title, - diaryDescription: diarySample.description) + let addDiaryViewController = DiaryDetailViewController() navigationController.pushViewController(addDiaryViewController, animated: true) } From 39faa7911bb191478dd171039126d8755ef9ece8 Mon Sep 17 00:00:00 2001 From: Serena Date: Tue, 12 Sep 2023 10:23:50 +0900 Subject: [PATCH 08/34] =?UTF-8?q?feat:=20createDiaryData=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 --- .../DiaryDetailViewController.swift | 18 +++++++++++++++++ Diary/Manager/AppManager.swift | 20 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index a57d95615..c02118b07 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -7,6 +7,11 @@ import UIKit +protocol DiaryDetailViewControllerDelegate: AnyObject { + func createDiaryData(text: String) + func updateDiaryData() +} + final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { private let textView: UITextView = { let textView = UITextView() @@ -16,6 +21,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable }() private var diaryEntity: DiaryEntity? + weak var delegate: DiaryDetailViewControllerDelegate? init(diaryEntity: DiaryEntity? = nil) { self.diaryEntity = diaryEntity @@ -37,6 +43,8 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + + saveDiaryContents() } private func configureUI() { @@ -56,6 +64,16 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable view.backgroundColor = .systemBackground navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) } + + private func saveDiaryContents() { + if diaryEntity == nil { + let text = textView.text ?? "" + + delegate?.createDiaryData(text: text) + } else { + delegate?.updateDiaryData() + } + } } // MARK: - Button Action diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 2db526a19..77c700442 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -39,10 +39,26 @@ final class AppManager { // MARK: - MainViewControllerDelegate extension AppManager: MainViewControllerDelegate { func didTappedRightAddButton() { - let diarySample = DiarySample() - let todayDate = dateFormatter.string(from: Date()) let addDiaryViewController = DiaryDetailViewController() + addDiaryViewController.delegate = self navigationController.pushViewController(addDiaryViewController, animated: true) } } + +// MARK: - DiaryDetailViewControllerDelegate +extension AppManager: DiaryDetailViewControllerDelegate { + func createDiaryData(text: String) { + let separatedText = text.split(separator: "\n", maxSplits: 1) + let titleText = separatedText.first?.description ?? "" + let bodyText = separatedText.last?.description ?? "" + let date = Date().timeIntervalSince1970 + + diaryDataManager.createDiaryData(title: titleText, body: bodyText, date: date) + diaryDataManager.saveContext() + } + + func updateDiaryData() { + + } +} From c5c5b6022c5a7080f148008a5c9c4664d9780d21 Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 10:48:01 +0900 Subject: [PATCH 09/34] =?UTF-8?q?feat:=20viewWillAppear=20=EC=8B=9C=20data?= =?UTF-8?q?Fetch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/MainViewController.swift | 25 ++++++++++++++++------- Diary/Manager/AppManager.swift | 10 +++++++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index e5c3a6cb8..8321c8414 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -8,6 +8,7 @@ import UIKit protocol MainViewControllerDelegate: AnyObject { func didTappedRightAddButton() + func fetchDiaryContents(mainViewController: MainViewController) } final class MainViewController: UIViewController, AlertControllerShowable { @@ -16,7 +17,7 @@ final class MainViewController: UIViewController, AlertControllerShowable { } weak var delegate: MainViewControllerDelegate? - private let diaryEntity: [DiaryEntity] + private var diaryContents: [DiaryEntity] private let dateFormatter: DateFormatter private var diffableDatasource: UITableViewDiffableDataSource? @@ -30,8 +31,8 @@ final class MainViewController: UIViewController, AlertControllerShowable { return tableView }() - init(diaryEntity: [DiaryEntity], dateFormatter: DateFormatter) { - self.diaryEntity = diaryEntity + init(diaryContents: [DiaryEntity], dateFormatter: DateFormatter) { + self.diaryContents = diaryContents self.dateFormatter = dateFormatter super.init(nibName: nil, bundle: nil) @@ -48,9 +49,19 @@ final class MainViewController: UIViewController, AlertControllerShowable { setUpConstraints() setUpViewController() setUpTableViewDiffableDataSource() - setUpTableViewDiffableDataSourceSnapShot() } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + delegate?.fetchDiaryContents(mainViewController: self) + setUpTableViewDiffableDataSourceSnapShot(animated: false) + } + + func setUpDiaryEntity(diaryContents: [DiaryEntity]) { + self.diaryContents = diaryContents + } + private func configureUI() { view.addSubview(tableView) } @@ -104,12 +115,12 @@ extension MainViewController { }) } - private func setUpTableViewDiffableDataSourceSnapShot() { + private func setUpTableViewDiffableDataSourceSnapShot(animated: Bool = true) { var snapShot = NSDiffableDataSourceSnapshot() snapShot.appendSections([.main]) - snapShot.appendItems(diaryEntity) - diffableDatasource?.apply(snapShot) + snapShot.appendItems(diaryContents) + diffableDatasource?.apply(snapShot, animatingDifferences: animated) } } diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 77c700442..c719b88ed 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -28,8 +28,8 @@ final class AppManager { } func start() { - guard let diaryData = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } - let mainViewController = MainViewController(diaryEntity: diaryData, dateFormatter: dateFormatter) + guard let diaryContents = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } + let mainViewController = MainViewController(diaryContents: diaryContents, dateFormatter: dateFormatter) mainViewController.delegate = self navigationController.viewControllers = [mainViewController] @@ -44,6 +44,12 @@ extension AppManager: MainViewControllerDelegate { addDiaryViewController.delegate = self navigationController.pushViewController(addDiaryViewController, animated: true) } + + func fetchDiaryContents(mainViewController: MainViewController) { + guard let diaryContents = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } + + mainViewController.setUpDiaryEntity(diaryContents: diaryContents) + } } // MARK: - DiaryDetailViewControllerDelegate From 469ba3ad2e7a98d42f459236df60c31c251ef239 Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 11:26:56 +0900 Subject: [PATCH 10/34] =?UTF-8?q?feat:=20DiaryDetailViewController=20Updat?= =?UTF-8?q?e=20=EA=B8=B0=EB=8A=A5=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DiaryDetailViewController.swift | 24 ++++++++++--- Diary/Controller/MainViewController.swift | 7 +++- Diary/Manager/AppManager.swift | 36 ++++++++++++++----- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index c02118b07..1c312a5c3 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -9,7 +9,7 @@ import UIKit protocol DiaryDetailViewControllerDelegate: AnyObject { func createDiaryData(text: String) - func updateDiaryData() + func updateDiaryData(diaryEntity: DiaryEntity, text: String) } final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { @@ -20,9 +20,12 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable return textView }() + private lazy var isUpdate = diaryEntity != nil private var diaryEntity: DiaryEntity? weak var delegate: DiaryDetailViewControllerDelegate? + + init(diaryEntity: DiaryEntity? = nil) { self.diaryEntity = diaryEntity @@ -39,6 +42,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable configureUI() setUpConstraints() setUpViewController() + setUpText() } override func viewWillDisappear(_ animated: Bool) { @@ -65,13 +69,23 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) } + private func setUpText() { + guard let diaryEntity else { return } + + if isUpdate { + textView.text = diaryEntity.title + "\n" + diaryEntity.body + } + } + private func saveDiaryContents() { - if diaryEntity == nil { - let text = textView.text ?? "" + let text = textView.text ?? "" + + if isUpdate { + guard let diaryEntity else { return } - delegate?.createDiaryData(text: text) + delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) } else { - delegate?.updateDiaryData() + delegate?.createDiaryData(text: text) } } } diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index 8321c8414..baf0cd721 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -9,6 +9,7 @@ import UIKit protocol MainViewControllerDelegate: AnyObject { func didTappedRightAddButton() func fetchDiaryContents(mainViewController: MainViewController) + func didSelectRowAt(diaryContent: DiaryEntity) } final class MainViewController: UIViewController, AlertControllerShowable { @@ -25,7 +26,6 @@ final class MainViewController: UIViewController, AlertControllerShowable { let tableView = UITableView() tableView.delegate = self - tableView.allowsSelection = false tableView.register(MainTableViewCell.self, forCellReuseIdentifier: MainTableViewCell.indentifier) tableView.translatesAutoresizingMaskIntoConstraints = false return tableView @@ -84,6 +84,11 @@ final class MainViewController: UIViewController, AlertControllerShowable { // MARK: - TableView Delegate extension MainViewController: UITableViewDelegate { + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + delegate?.didSelectRowAt(diaryContent: diaryContents[indexPath.row]) + tableView.deselectRow(at: indexPath, animated: true) + } + func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let shareAction: UIContextualAction = .init(style: .normal, title: "Share") { _, _, _ in diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index c719b88ed..c599366d8 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -38,11 +38,18 @@ final class AppManager { // MARK: - MainViewControllerDelegate extension AppManager: MainViewControllerDelegate { + func didSelectRowAt(diaryContent: DiaryEntity) { + let diaryDetailViewController = DiaryDetailViewController(diaryEntity: diaryContent) + + diaryDetailViewController.delegate = self + navigationController.pushViewController(diaryDetailViewController, animated: true) + } + func didTappedRightAddButton() { - let addDiaryViewController = DiaryDetailViewController() + let diaryDetailViewController = DiaryDetailViewController() - addDiaryViewController.delegate = self - navigationController.pushViewController(addDiaryViewController, animated: true) + diaryDetailViewController.delegate = self + navigationController.pushViewController(diaryDetailViewController, animated: true) } func fetchDiaryContents(mainViewController: MainViewController) { @@ -55,16 +62,29 @@ extension AppManager: MainViewControllerDelegate { // MARK: - DiaryDetailViewControllerDelegate extension AppManager: DiaryDetailViewControllerDelegate { func createDiaryData(text: String) { - let separatedText = text.split(separator: "\n", maxSplits: 1) - let titleText = separatedText.first?.description ?? "" - let bodyText = separatedText.last?.description ?? "" + guard let (title, body) = convertDiaryData(text: text) else { return } let date = Date().timeIntervalSince1970 - diaryDataManager.createDiaryData(title: titleText, body: bodyText, date: date) + diaryDataManager.createDiaryData(title: title, body: body, date: date) diaryDataManager.saveContext() } - func updateDiaryData() { + func updateDiaryData(diaryEntity: DiaryEntity, text: String) { + guard let (title, body) = convertDiaryData(text: text) else { return } + let date = Date().timeIntervalSince1970 + + diaryEntity.title = title + diaryEntity.body = body + diaryEntity.date = date + diaryDataManager.saveContext() + } + + private func convertDiaryData(text: String) -> (String, String)? { + let separatedText = text.split(separator: "\n", maxSplits: 1) + guard let titleText = separatedText.first?.description else { return nil } + + let bodyText = separatedText.last?.description ?? "" + return (titleText, bodyText) } } From 723ae2952b491f08c0c2c208cb31de96e037df4a Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 11:28:03 +0900 Subject: [PATCH 11/34] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=BB=A4=EB=B0=8B=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 1c312a5c3..acc73f96b 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -24,8 +24,6 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable private var diaryEntity: DiaryEntity? weak var delegate: DiaryDetailViewControllerDelegate? - - init(diaryEntity: DiaryEntity? = nil) { self.diaryEntity = diaryEntity From 701dba8f71d4c9cc85b81d664ccf5168ca63de83 Mon Sep 17 00:00:00 2001 From: Serena Date: Tue, 12 Sep 2023 12:49:54 +0900 Subject: [PATCH 12/34] =?UTF-8?q?feat:=20deleteAction=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/MainViewController.swift | 10 ++++++---- Diary/Manager/AppManager.swift | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index baf0cd721..a2dd5e6c1 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -10,6 +10,7 @@ protocol MainViewControllerDelegate: AnyObject { func didTappedRightAddButton() func fetchDiaryContents(mainViewController: MainViewController) func didSelectRowAt(diaryContent: DiaryEntity) + func deleteDiaryContent(diaryContent: DiaryEntity) } final class MainViewController: UIViewController, AlertControllerShowable { @@ -95,7 +96,7 @@ extension MainViewController: UITableViewDelegate { } let deleteAction: UIContextualAction = .init(style: .destructive, title: "Delete") { _, _, _ in - self.didTappedDeleteAction() + self.didTappedDeleteAction(index: indexPath.row) } let swipeActionConfiguration: UISwipeActionsConfiguration = .init(actions: [deleteAction, shareAction]) @@ -134,13 +135,14 @@ extension MainViewController { @objc private func didTappedRightAddButton() { delegate?.didTappedRightAddButton() - } - private func didTappedDeleteAction() { + private func didTappedDeleteAction(index: Int) { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in - + self.delegate?.deleteDiaryContent(diaryContent: self.diaryContents[index]) + self.diaryContents.remove(at: index) + self.setUpTableViewDiffableDataSourceSnapShot() } showAlertController(title: "진짜요?", diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index c599366d8..8deea45e6 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -57,6 +57,11 @@ extension AppManager: MainViewControllerDelegate { mainViewController.setUpDiaryEntity(diaryContents: diaryContents) } + + func deleteDiaryContent(diaryContent: DiaryEntity) { + diaryDataManager.deleteData(entity: diaryContent) + diaryDataManager.saveContext() + } } // MARK: - DiaryDetailViewControllerDelegate From f5dee66fb85f817c20c2c2df5882de07d9e05b81 Mon Sep 17 00:00:00 2001 From: Serena Date: Tue, 12 Sep 2023 13:30:56 +0900 Subject: [PATCH 13/34] =?UTF-8?q?feat:=20DiaryDetailViewController=20Delet?= =?UTF-8?q?e=20=EB=A9=94=EC=86=8C=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 5 ++++- Diary/Manager/AppManager.swift | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index acc73f96b..a14e061d5 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -10,6 +10,7 @@ import UIKit protocol DiaryDetailViewControllerDelegate: AnyObject { func createDiaryData(text: String) func updateDiaryData(diaryEntity: DiaryEntity, text: String) + func deleteDiaryData(diaryEntity: DiaryEntity) } final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { @@ -108,7 +109,9 @@ extension DiaryDetailViewController { private func didTappedDeleteAction() { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in - + if let diaryEntity = self.diaryEntity { + self.delegate?.deleteDiaryData(diaryEntity: diaryEntity) + } } showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 8deea45e6..94a64851d 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -84,6 +84,11 @@ extension AppManager: DiaryDetailViewControllerDelegate { diaryDataManager.saveContext() } + func deleteDiaryData(diaryEntity: DiaryEntity) { + diaryDataManager.deleteData(entity: diaryEntity) + navigationController.popViewController(animated: true) + } + private func convertDiaryData(text: String) -> (String, String)? { let separatedText = text.split(separator: "\n", maxSplits: 1) guard let titleText = separatedText.first?.description else { return nil } From 500f635b8e9ae71407accb6cc75aaa014606d300 Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 13:40:24 +0900 Subject: [PATCH 14/34] =?UTF-8?q?feat:=20Update,=20Create=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 4 ++++ Diary/Manager/AppManager.swift | 3 +++ 2 files changed, 7 insertions(+) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index a14e061d5..5dc476c87 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -11,6 +11,7 @@ protocol DiaryDetailViewControllerDelegate: AnyObject { func createDiaryData(text: String) func updateDiaryData(diaryEntity: DiaryEntity, text: String) func deleteDiaryData(diaryEntity: DiaryEntity) + func popDiaryDetailViewController() } final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { @@ -112,6 +113,9 @@ extension DiaryDetailViewController { if let diaryEntity = self.diaryEntity { self.delegate?.deleteDiaryData(diaryEntity: diaryEntity) } + + self.textView.text = "" + self.delegate?.popDiaryDetailViewController() } showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 94a64851d..bdb5130ac 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -86,6 +86,9 @@ extension AppManager: DiaryDetailViewControllerDelegate { func deleteDiaryData(diaryEntity: DiaryEntity) { diaryDataManager.deleteData(entity: diaryEntity) + } + + func popDiaryDetailViewController() { navigationController.popViewController(animated: true) } From 9fcf716b1cae7ece3ffa8d4f8e92777da1f8e092 Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 13:51:41 +0900 Subject: [PATCH 15/34] =?UTF-8?q?feat:=20TextView=20EndEditing=EC=8B=9C=20?= =?UTF-8?q?Save=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 5dc476c87..1f39b8e1c 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -15,9 +15,11 @@ protocol DiaryDetailViewControllerDelegate: AnyObject { } final class DiaryDetailViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { - private let textView: UITextView = { + private lazy var textView: UITextView = { let textView = UITextView() + textView.delegate = self + textView.keyboardDismissMode = .onDrag textView.translatesAutoresizingMaskIntoConstraints = false return textView }() @@ -121,3 +123,10 @@ extension DiaryDetailViewController { showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) } } + +// MARK: - TextView Delegate +extension DiaryDetailViewController: UITextViewDelegate { + func textViewDidEndEditing(_ textView: UITextView) { + saveDiaryContents() + } +} From 6c34cff3dd5e13ab96fcabf177da5b6e366ba51f Mon Sep 17 00:00:00 2001 From: Serena Date: Tue, 12 Sep 2023 14:02:01 +0900 Subject: [PATCH 16/34] =?UTF-8?q?feat:=20NotificationCenter=20Observer=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 1f39b8e1c..ae3db4d16 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -47,10 +47,17 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable setUpText() } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + addObserver() + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) saveDiaryContents() + removeObserver() } private func configureUI() { @@ -79,6 +86,15 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable } } + private func addObserver() { + NotificationCenter.default.addObserver(self, selector: #selector(saveDiaryContents), name: UIApplication.didEnterBackgroundNotification, object: nil) + } + + private func removeObserver() { + NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) + } + + @objc private func saveDiaryContents() { let text = textView.text ?? "" From 97bb2915efa870c48e31debcb2a193528fca064c Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 14:58:51 +0900 Subject: [PATCH 17/34] =?UTF-8?q?feat:=20background=20=EC=8B=9C=20create?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 9 ++++++--- Diary/Manager/AppManager.swift | 7 ++++--- Diary/Manager/DiaryCoreDataManager.swift | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index ae3db4d16..d70b289c1 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -8,7 +8,7 @@ import UIKit protocol DiaryDetailViewControllerDelegate: AnyObject { - func createDiaryData(text: String) + func createDiaryData(text: String) -> DiaryEntity? func updateDiaryData(diaryEntity: DiaryEntity, text: String) func deleteDiaryData(diaryEntity: DiaryEntity) func popDiaryDetailViewController() @@ -24,7 +24,10 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable return textView }() - private lazy var isUpdate = diaryEntity != nil + private var isUpdate: Bool { + diaryEntity != nil + } + private var diaryEntity: DiaryEntity? weak var delegate: DiaryDetailViewControllerDelegate? @@ -103,7 +106,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) } else { - delegate?.createDiaryData(text: text) + diaryEntity = delegate?.createDiaryData(text: text) } } } diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index bdb5130ac..9aade6080 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -66,12 +66,13 @@ extension AppManager: MainViewControllerDelegate { // MARK: - DiaryDetailViewControllerDelegate extension AppManager: DiaryDetailViewControllerDelegate { - func createDiaryData(text: String) { - guard let (title, body) = convertDiaryData(text: text) else { return } + func createDiaryData(text: String) -> DiaryEntity? { + guard let (title, body) = convertDiaryData(text: text) else { return nil } let date = Date().timeIntervalSince1970 + let diaryEntity = diaryDataManager.createDiaryData(title: title, body: body, date: date) - diaryDataManager.createDiaryData(title: title, body: body, date: date) diaryDataManager.saveContext() + return diaryEntity } func updateDiaryData(diaryEntity: DiaryEntity, text: String) { diff --git a/Diary/Manager/DiaryCoreDataManager.swift b/Diary/Manager/DiaryCoreDataManager.swift index 073f7c29e..2489414b7 100644 --- a/Diary/Manager/DiaryCoreDataManager.swift +++ b/Diary/Manager/DiaryCoreDataManager.swift @@ -6,11 +6,12 @@ // final class DiaryCoreDataManager: CoreDataManager { - func createDiaryData(title: String, body: String, date: Double) { + func createDiaryData(title: String, body: String, date: Double) -> DiaryEntity { let entity = DiaryEntity(context: context) entity.title = title entity.body = body entity.date = date + return entity } } From 9974d9a6895fd4b54ba689509d310c3ab7f880c0 Mon Sep 17 00:00:00 2001 From: Serena Date: Tue, 12 Sep 2023 15:17:48 +0900 Subject: [PATCH 18/34] =?UTF-8?q?feat:=20Activity=20Share=20Action=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 --- Diary/Controller/DiaryDetailViewController.swift | 8 +++++++- Diary/Controller/MainViewController.swift | 11 +++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index d70b289c1..ad1f3cce0 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -116,7 +116,7 @@ extension DiaryDetailViewController { @objc func didTappedMoreButton() { let shareAction = UIAlertAction(title: "Share...", style: .default) { _ in - self.showActivityViewController(items: [""]) + self.didTappedShareAction() } let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { _ in @@ -141,6 +141,12 @@ extension DiaryDetailViewController { showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) } + + private func didTappedShareAction() { + let sharedItem = self.textView.text + + self.showActivityViewController(items: [sharedItem as Any]) + } } // MARK: - TextView Delegate diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index a2dd5e6c1..82be90aa6 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -13,7 +13,7 @@ protocol MainViewControllerDelegate: AnyObject { func deleteDiaryContent(diaryContent: DiaryEntity) } -final class MainViewController: UIViewController, AlertControllerShowable { +final class MainViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { enum Section { case main } @@ -92,7 +92,7 @@ extension MainViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let shareAction: UIContextualAction = .init(style: .normal, title: "Share") { _, _, _ in - + self.didTappedShareAction(index: indexPath.row) } let deleteAction: UIContextualAction = .init(style: .destructive, title: "Delete") { _, _, _ in @@ -150,4 +150,11 @@ extension MainViewController { style: .alert, actions: [cancelAction, deleteAction]) } + + private func didTappedShareAction(index: Int) { + let entity = self.diaryContents[index] + let sharedItem = entity.title + "\n" + entity.body + + self.showActivityViewController(items: [sharedItem as Any]) + } } From 926989943cf4f8e0a8800410a429af73e39da165 Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 15:36:43 +0900 Subject: [PATCH 19/34] =?UTF-8?q?feat:=20date=20=EC=B6=9C=EB=A0=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20becomeResponder=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 6 +++++- Diary/Manager/AppManager.swift | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index ad1f3cce0..ffc397879 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -20,6 +20,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable textView.delegate = self textView.keyboardDismissMode = .onDrag + textView.becomeFirstResponder() textView.translatesAutoresizingMaskIntoConstraints = false return textView }() @@ -29,9 +30,11 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable } private var diaryEntity: DiaryEntity? + private let date: String weak var delegate: DiaryDetailViewControllerDelegate? - init(diaryEntity: DiaryEntity? = nil) { + init(date: String, diaryEntity: DiaryEntity? = nil) { + self.date = date self.diaryEntity = diaryEntity super.init(nibName: nil, bundle: nil) @@ -78,6 +81,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable private func setUpViewController() { view.backgroundColor = .systemBackground + navigationItem.title = date navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) } diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 9aade6080..979558eeb 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -16,7 +16,7 @@ final class AppManager { dateFormatter.locale = Locale(identifier: deviceLocale) dateFormatter.timeZone = TimeZone.current - dateFormatter.dateFormat = "yyyy년 MM월 dd일" + dateFormatter.dateStyle = .long return dateFormatter }() @@ -39,14 +39,17 @@ final class AppManager { // MARK: - MainViewControllerDelegate extension AppManager: MainViewControllerDelegate { func didSelectRowAt(diaryContent: DiaryEntity) { - let diaryDetailViewController = DiaryDetailViewController(diaryEntity: diaryContent) + let date = Date(timeIntervalSince1970: diaryContent.date) + let formattedDate = dateFormatter.string(from: date) + let diaryDetailViewController = DiaryDetailViewController(date: formattedDate, diaryEntity: diaryContent) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) } func didTappedRightAddButton() { - let diaryDetailViewController = DiaryDetailViewController() + let todayDate = dateFormatter.string(from: Date()) + let diaryDetailViewController = DiaryDetailViewController(date: todayDate) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) From bc89e580507d90d480db6a61672760fc5ee205ae Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 16:02:02 +0900 Subject: [PATCH 20/34] =?UTF-8?q?feat:=20diffableDataSource=20delete?= =?UTF-8?q?=EC=8B=9C=20bottom=20Constraint=20=EC=B6=A9=EB=8F=8C=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/View/MainTableViewCell.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Diary/View/MainTableViewCell.swift b/Diary/View/MainTableViewCell.swift index ef05b8a8b..73046a6f3 100644 --- a/Diary/View/MainTableViewCell.swift +++ b/Diary/View/MainTableViewCell.swift @@ -84,10 +84,13 @@ extension MainTableViewCell { NSLayoutConstraint.activate([ mainStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10), mainStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10), - mainStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5), - mainStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5) + mainStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5) ]) + let mainStackViewBottomConstraint = mainStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5) + + mainStackViewBottomConstraint.priority = .init(999) + mainStackViewBottomConstraint.isActive = true dateLabel.setContentCompressionResistancePriority(.required, for: .horizontal) previewLabel.setContentHuggingPriority(.init(1), for: .horizontal) } From b5ae8685939fe7ddb501f82a8bdb7e0180066a5e Mon Sep 17 00:00:00 2001 From: Zion Date: Tue, 12 Sep 2023 17:01:06 +0900 Subject: [PATCH 21/34] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20model=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 8 -------- Diary/Model/DiaryContent.swift | 21 --------------------- Diary/Model/DiarySample.swift | 11 ----------- 3 files changed, 40 deletions(-) delete mode 100644 Diary/Model/DiaryContent.swift delete mode 100644 Diary/Model/DiarySample.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 8c9c9832b..c806899a5 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */; }; - 5BBC443B2A9F276100C528DD /* DiarySample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC443A2A9F276100C528DD /* DiarySample.swift */; }; 5BBC443D2A9F30ED00C528DD /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */; }; 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */; }; 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */; }; @@ -22,7 +21,6 @@ D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */; }; D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */; }; - D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */; }; D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */; }; D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */; }; D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */; }; @@ -30,7 +28,6 @@ /* Begin PBXFileReference section */ 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTableViewCell.swift; sourceTree = ""; }; - 5BBC443A2A9F276100C528DD /* DiarySample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiarySample.swift; sourceTree = ""; }; 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertControllerShowable.swift; sourceTree = ""; }; 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityViewControllerShowable.swift; sourceTree = ""; }; @@ -46,7 +43,6 @@ D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryCoreDataManager.swift; sourceTree = ""; }; - D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContent.swift; sourceTree = ""; }; D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = ""; }; D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifiable.swift; sourceTree = ""; }; @@ -94,8 +90,6 @@ isa = PBXGroup; children = ( D2BCA2B22AAF3A8700D55F4C /* CoreData */, - D2C1FBEE2A9F058000526DA5 /* DiaryContent.swift */, - 5BBC443A2A9F276100C528DD /* DiarySample.swift */, ); path = Model; sourceTree = ""; @@ -270,14 +264,12 @@ C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */, D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */, - D2C1FBEF2A9F058000526DA5 /* DiaryContent.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */, D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */, - 5BBC443B2A9F276100C528DD /* DiarySample.swift in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Diary/Model/DiaryContent.swift b/Diary/Model/DiaryContent.swift deleted file mode 100644 index 3e0b4c7b0..000000000 --- a/Diary/Model/DiaryContent.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// DiaryContent.swift -// Diary -// -// Created by Zion, Serena on 2023/08/30. -// - -import Foundation - -struct DiaryContent: Decodable, Hashable { - private let id: UUID = UUID() - let title: String - let body: String - let date: Double - - private enum CodingKeys: String, CodingKey { - case title - case body - case date = "created_at" - } -} diff --git a/Diary/Model/DiarySample.swift b/Diary/Model/DiarySample.swift deleted file mode 100644 index 2141aeeb0..000000000 --- a/Diary/Model/DiarySample.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// DiarySample.swift -// Diary -// -// Created by Zion, Serena on 2023/08/30. -// - -struct DiarySample { - let title = "드라고요롱이마초미미진사오미" - let description = "A wonderful serenity has taken possession of my entire soul, like these sweet mornings of spring which I enjoy with my whole heart. I am alone, and feel the charm of existence in this spot, which was created for the bliss of souls like mine.\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath\n\nI am so happy, my dear friend, so absorbed in the exquisite sense of mere tranquil existence, that I neglect my talents. I should be incapable of drawing a single stroke at the present moment; and yet I feel that I never was a greater artist than now.\n\nWhen, while the lovely valley teems with vapour around me, and the meridian sun strikes the upper surface of the impenetrable foliage of my trees, and but a few stray gleams steal into the inner sanctuary, I throw myself down among the tall grass by the trickling stream; and, as I lie close to the earth, a thousand unknown plants are noticed by me: when I hear the buzz of the little world among the stalks, and grow familiar with the countless indescribable forms of the insects and flies, then I feel the presence of the Almighty, who formed us in his own image, and the breath" -} From 021fc0f975093abcdc613ef2e42b7d175a53491c Mon Sep 17 00:00:00 2001 From: Serena Date: Thu, 14 Sep 2023 10:35:49 +0900 Subject: [PATCH 22/34] =?UTF-8?q?refactor:=20private=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index ffc397879..91089a99e 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -118,7 +118,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable // MARK: - Button Action extension DiaryDetailViewController { @objc - func didTappedMoreButton() { + private func didTappedMoreButton() { let shareAction = UIAlertAction(title: "Share...", style: .default) { _ in self.didTappedShareAction() } From 7125c8a4b6817dfedd2455d81dc183fd1457157c Mon Sep 17 00:00:00 2001 From: Zion Date: Thu, 14 Sep 2023 12:23:13 +0900 Subject: [PATCH 23/34] =?UTF-8?q?fix:=20title=EB=A7=8C=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=ED=95=A0=EA=B2=BD=EC=9A=B0=20body=EB=8F=84=20title?= =?UTF-8?q?=EC=B2=98=EB=9F=BC=20=EB=82=98=EC=98=A4=EB=8A=94=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/AppManager.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 979558eeb..05b650674 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -100,7 +100,8 @@ extension AppManager: DiaryDetailViewControllerDelegate { let separatedText = text.split(separator: "\n", maxSplits: 1) guard let titleText = separatedText.first?.description else { return nil } - let bodyText = separatedText.last?.description ?? "" + let removedTitleText = separatedText.dropFirst() + let bodyText = removedTitleText.count != 0 ? removedTitleText.description : "" return (titleText, bodyText) } From 21cc6ff7eb7588e0e9ee3fd485aea8cd26a31f3b Mon Sep 17 00:00:00 2001 From: Zion Date: Thu, 14 Sep 2023 12:56:31 +0900 Subject: [PATCH 24/34] =?UTF-8?q?fix:=20insertData=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20data=20Create=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EA=B0=92=20=EC=82=AD=EC=A0=9C,=20DiaryCoreDataMana?= =?UTF-8?q?ger=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 4 --- Diary/App/SceneDelegate.swift | 4 +-- .../DiaryDetailViewController.swift | 17 +++++------ Diary/Manager/AppManager.swift | 30 +++++++++---------- Diary/Manager/CoreDataManager.swift | 20 +++++++++++++ Diary/Manager/DiaryCoreDataManager.swift | 17 ----------- 6 files changed, 44 insertions(+), 48 deletions(-) delete mode 100644 Diary/Manager/DiaryCoreDataManager.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index c806899a5..0747842ff 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -20,7 +20,6 @@ D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */; }; D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */; }; D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; - D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */; }; D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */; }; D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */; }; D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */; }; @@ -42,7 +41,6 @@ D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; - D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryCoreDataManager.swift; sourceTree = ""; }; D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = ""; }; D2DB46862AA1A83B009D1926 /* ReuseIdentifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReuseIdentifiable.swift; sourceTree = ""; }; @@ -149,7 +147,6 @@ children = ( D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */, D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */, - D2BCA2B62AAF3B2300D55F4C /* DiaryCoreDataManager.swift */, ); path = Manager; sourceTree = ""; @@ -268,7 +265,6 @@ D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, - D2BCA2B72AAF3B2300D55F4C /* DiaryCoreDataManager.swift in Sources */, D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, ); diff --git a/Diary/App/SceneDelegate.swift b/Diary/App/SceneDelegate.swift index b7b791a59..5e0f8ab51 100644 --- a/Diary/App/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -14,9 +14,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let windowScene = (scene as? UIWindowScene) else { return } let navigationController = UINavigationController() - let diaryDataManager = DiaryCoreDataManager(name: "Diary") + let coreDataManager = CoreDataManager(name: "Diary") - appManager = AppManager(navigationController: navigationController, diaryDataManager: diaryDataManager) + appManager = AppManager(navigationController: navigationController, coreDataManager: coreDataManager) appManager?.start() window = UIWindow(windowScene: windowScene) window?.rootViewController = navigationController diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 91089a99e..667850a0b 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -8,7 +8,7 @@ import UIKit protocol DiaryDetailViewControllerDelegate: AnyObject { - func createDiaryData(text: String) -> DiaryEntity? + func createDiaryData(text: String) func updateDiaryData(diaryEntity: DiaryEntity, text: String) func deleteDiaryData(diaryEntity: DiaryEntity) func popDiaryDetailViewController() @@ -25,16 +25,14 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable return textView }() - private var isUpdate: Bool { - diaryEntity != nil - } - + private var isUpdate: Bool private var diaryEntity: DiaryEntity? private let date: String weak var delegate: DiaryDetailViewControllerDelegate? - init(date: String, diaryEntity: DiaryEntity? = nil) { + init(date: String, isUpdate: Bool = true, diaryEntity: DiaryEntity? = nil) { self.date = date + self.isUpdate = isUpdate self.diaryEntity = diaryEntity super.init(nibName: nil, bundle: nil) @@ -88,9 +86,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable private func setUpText() { guard let diaryEntity else { return } - if isUpdate { - textView.text = diaryEntity.title + "\n" + diaryEntity.body - } + textView.text = diaryEntity.title + "\n" + diaryEntity.body } private func addObserver() { @@ -110,7 +106,8 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) } else { - diaryEntity = delegate?.createDiaryData(text: text) + isUpdate = true + delegate?.createDiaryData(text: text) } } } diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 05b650674..fdf4a43f1 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -20,15 +20,15 @@ final class AppManager { return dateFormatter }() - private let diaryDataManager: DiaryCoreDataManager + private let coreDataManager: CoreDataManager - init(navigationController: UINavigationController, diaryDataManager: DiaryCoreDataManager) { + init(navigationController: UINavigationController, coreDataManager: CoreDataManager) { self.navigationController = navigationController - self.diaryDataManager = diaryDataManager + self.coreDataManager = coreDataManager } func start() { - guard let diaryContents = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } + guard let diaryContents = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } let mainViewController = MainViewController(diaryContents: diaryContents, dateFormatter: dateFormatter) mainViewController.delegate = self @@ -49,33 +49,33 @@ extension AppManager: MainViewControllerDelegate { func didTappedRightAddButton() { let todayDate = dateFormatter.string(from: Date()) - let diaryDetailViewController = DiaryDetailViewController(date: todayDate) + let diaryDetailViewController = DiaryDetailViewController(date: todayDate, isUpdate: false) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) } func fetchDiaryContents(mainViewController: MainViewController) { - guard let diaryContents = try? diaryDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } + guard let diaryContents = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } mainViewController.setUpDiaryEntity(diaryContents: diaryContents) } func deleteDiaryContent(diaryContent: DiaryEntity) { - diaryDataManager.deleteData(entity: diaryContent) - diaryDataManager.saveContext() + coreDataManager.deleteData(entity: diaryContent) + coreDataManager.saveContext() } } // MARK: - DiaryDetailViewControllerDelegate extension AppManager: DiaryDetailViewControllerDelegate { - func createDiaryData(text: String) -> DiaryEntity? { - guard let (title, body) = convertDiaryData(text: text) else { return nil } + func createDiaryData(text: String) { + guard let (title, body) = convertDiaryData(text: text) else { return } let date = Date().timeIntervalSince1970 - let diaryEntity = diaryDataManager.createDiaryData(title: title, body: body, date: date) + let diaryEntityProperties: [String: Any] = ["title": title, "body": body, "date": date] - diaryDataManager.saveContext() - return diaryEntity + coreDataManager.insertData(entityName: "DiaryEntity", entityProperties: diaryEntityProperties) + coreDataManager.saveContext() } func updateDiaryData(diaryEntity: DiaryEntity, text: String) { @@ -85,11 +85,11 @@ extension AppManager: DiaryDetailViewControllerDelegate { diaryEntity.title = title diaryEntity.body = body diaryEntity.date = date - diaryDataManager.saveContext() + coreDataManager.saveContext() } func deleteDiaryData(diaryEntity: DiaryEntity) { - diaryDataManager.deleteData(entity: diaryEntity) + coreDataManager.deleteData(entity: diaryEntity) } func popDiaryDetailViewController() { diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index 415d19edd..fbcc280a1 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -28,6 +28,26 @@ class CoreDataManager { return data } + func createDiaryData2(title: String, body: String, date: Double) { + let dictionary = ["1":"a", "2":"b", "3":"c", "4":"d"] + let entity = NSEntityDescription.entity(forEntityName: "DiaryEntity", in: context) + let managedObject = NSManagedObject(entity: entity!, insertInto: nil) + + for element in dictionary { + managedObject.setValue(element.value, forKey: element.key) + } + } + + func insertData(entityName: String, entityProperties: [String: Any]) { + if let entity = NSEntityDescription.entity(forEntityName: entityName, in: context) { + let managedObject = NSManagedObject(entity: entity, insertInto: nil) + + for entityProperty in entityProperties { + managedObject.setValue(entityProperty.value, forKey: entityProperty.key) + } + } + } + func deleteData(entity: NSManagedObject) { context.delete(entity) } diff --git a/Diary/Manager/DiaryCoreDataManager.swift b/Diary/Manager/DiaryCoreDataManager.swift deleted file mode 100644 index 2489414b7..000000000 --- a/Diary/Manager/DiaryCoreDataManager.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// DiaryCoreDataManager.swift -// Diary -// -// Created by Zion, Serena on 2023/09/11. -// - -final class DiaryCoreDataManager: CoreDataManager { - func createDiaryData(title: String, body: String, date: Double) -> DiaryEntity { - let entity = DiaryEntity(context: context) - - entity.title = title - entity.body = body - entity.date = date - return entity - } -} From 678318f2667e296f90f0f8e5b354909ea9172ae8 Mon Sep 17 00:00:00 2001 From: Serena Date: Thu, 14 Sep 2023 13:00:10 +0900 Subject: [PATCH 25/34] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/CoreDataManager.swift | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index fbcc280a1..da7352aa5 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -28,16 +28,6 @@ class CoreDataManager { return data } - func createDiaryData2(title: String, body: String, date: Double) { - let dictionary = ["1":"a", "2":"b", "3":"c", "4":"d"] - let entity = NSEntityDescription.entity(forEntityName: "DiaryEntity", in: context) - let managedObject = NSManagedObject(entity: entity!, insertInto: nil) - - for element in dictionary { - managedObject.setValue(element.value, forKey: element.key) - } - } - func insertData(entityName: String, entityProperties: [String: Any]) { if let entity = NSEntityDescription.entity(forEntityName: entityName, in: context) { let managedObject = NSManagedObject(entity: entity, insertInto: nil) From d97d383846a5eb4d616e63680142a0bba824e2d4 Mon Sep 17 00:00:00 2001 From: Serena Date: Thu, 14 Sep 2023 14:20:42 +0900 Subject: [PATCH 26/34] =?UTF-8?q?refactor:=20insertData=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/CoreDataManager.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index da7352aa5..1f37c49f6 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -30,7 +30,7 @@ class CoreDataManager { func insertData(entityName: String, entityProperties: [String: Any]) { if let entity = NSEntityDescription.entity(forEntityName: entityName, in: context) { - let managedObject = NSManagedObject(entity: entity, insertInto: nil) + let managedObject = NSManagedObject(entity: entity, insertInto: context) for entityProperty in entityProperties { managedObject.setValue(entityProperty.value, forKey: entityProperty.key) @@ -43,8 +43,6 @@ class CoreDataManager { } func saveContext () { - let context = persistentContainer.viewContext - if context.hasChanges { do { try context.save() From c41d293e8b8e38f5603da40dc384bb15fe4e4798 Mon Sep 17 00:00:00 2001 From: Zion Date: Thu, 14 Sep 2023 15:28:44 +0900 Subject: [PATCH 27/34] =?UTF-8?q?feat:=20CoreData=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20DiaryContentsDTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 40 +++++++++++++---- .../DiaryDetailViewController.swift | 42 +++++++++-------- Diary/Controller/MainViewController.swift | 45 ++++++++++--------- Diary/Manager/AppManager.swift | 23 +++------- .../Diary.xcdatamodel/contents | 3 +- .../CoreData/DiaryEntity+CoreDataClass.swift | 2 +- .../DiaryEntity+CoreDataProperties.swift | 5 ++- Diary/Model/DTO/DiaryContentsDTO.swift | 15 +++++++ Diary/UseCase/MainViewControllerUseCase.swift | 39 ++++++++++++++++ 9 files changed, 143 insertions(+), 71 deletions(-) create mode 100644 Diary/Model/DTO/DiaryContentsDTO.swift create mode 100644 Diary/UseCase/MainViewControllerUseCase.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 0747842ff..eb0b848d2 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -11,14 +11,16 @@ 5BBC443D2A9F30ED00C528DD /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */; }; 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */; }; 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */; }; + 5BF1B2D72AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */; }; + 5BF1B2D82AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */; }; + 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */; }; + 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */; }; C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE24284DF28600741E8F /* AppDelegate.swift */; }; C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE26284DF28600741E8F /* SceneDelegate.swift */; }; C739AE29284DF28600741E8F /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* MainViewController.swift */; }; C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */; }; C739AE31284DF28600741E8F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C739AE30284DF28600741E8F /* Assets.xcassets */; }; C739AE34284DF28600741E8F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C739AE32284DF28600741E8F /* LaunchScreen.storyboard */; }; - D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */; }; - D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */; }; D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */; }; D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */; }; @@ -30,6 +32,10 @@ 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertControllerShowable.swift; sourceTree = ""; }; 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityViewControllerShowable.swift; sourceTree = ""; }; + 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; + 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; + 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; + 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContentsDTO.swift; sourceTree = ""; }; C739AE21284DF28600741E8F /* Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diary.app; sourceTree = BUILT_PRODUCTS_DIR; }; C739AE24284DF28600741E8F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C739AE26284DF28600741E8F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -38,8 +44,6 @@ C739AE30284DF28600741E8F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C739AE33284DF28600741E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C739AE35284DF28600741E8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; - D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; D2C1FBF22A9F0A0900526DA5 /* DiaryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewController.swift; sourceTree = ""; }; D2C1FBF52A9F1EC100526DA5 /* AppManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppManager.swift; sourceTree = ""; }; @@ -87,6 +91,7 @@ 5BBC44362A9F025500C528DD /* Model */ = { isa = PBXGroup; children = ( + 5BF1B2DC2AB2DA7D00FDC1A5 /* DTO */, D2BCA2B22AAF3A8700D55F4C /* CoreData */, ); path = Model; @@ -100,6 +105,22 @@ path = Resource; sourceTree = ""; }; + 5BF1B2DB2AB2D9E500FDC1A5 /* UseCase */ = { + isa = PBXGroup; + children = ( + 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */, + ); + path = UseCase; + sourceTree = ""; + }; + 5BF1B2DC2AB2DA7D00FDC1A5 /* DTO */ = { + isa = PBXGroup; + children = ( + 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */, + ); + path = DTO; + sourceTree = ""; + }; C739AE18284DF28600741E8F = { isa = PBXGroup; children = ( @@ -124,6 +145,7 @@ D2DB46852AA1A7BC009D1926 /* Protocol */, 5BBC44372A9F025A00C528DD /* Resource */, 5BBC44362A9F025500C528DD /* Model */, + 5BF1B2DB2AB2D9E500FDC1A5 /* UseCase */, 5BBC44352A9F025000C528DD /* View */, 5BBC44342A9F024B00C528DD /* Controller */, D2C1FBF42A9F1EA400526DA5 /* Manager */, @@ -136,8 +158,8 @@ isa = PBXGroup; children = ( C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, - D2BCA2AE2AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift */, - D2BCA2AF2AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift */, + 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */, + 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */, ); path = CoreData; sourceTree = ""; @@ -254,19 +276,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5BF1B2D72AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */, 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */, 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */, C739AE29284DF28600741E8F /* MainViewController.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, + 5BF1B2D82AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */, - D2BCA2B12AAF3A7900D55F4C /* DiaryEntity+CoreDataProperties.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, + 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, - D2BCA2B02AAF3A7900D55F4C /* DiaryEntity+CoreDataClass.swift in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, + 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 667850a0b..b4da32ba1 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -25,15 +25,13 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable return textView }() - private var isUpdate: Bool - private var diaryEntity: DiaryEntity? + private var diaryContent: DiaryContentsDTO private let date: String weak var delegate: DiaryDetailViewControllerDelegate? - init(date: String, isUpdate: Bool = true, diaryEntity: DiaryEntity? = nil) { + init(date: String, diaryContent: DiaryContentsDTO) { self.date = date - self.isUpdate = isUpdate - self.diaryEntity = diaryEntity + self.diaryContent = diaryContent super.init(nibName: nil, bundle: nil) } @@ -84,9 +82,9 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable } private func setUpText() { - guard let diaryEntity else { return } - - textView.text = diaryEntity.title + "\n" + diaryEntity.body +// guard let diaryEntity else { return } +// +// textView.text = diaryEntity.title + "\n" + diaryEntity.body } private func addObserver() { @@ -101,14 +99,14 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable private func saveDiaryContents() { let text = textView.text ?? "" - if isUpdate { - guard let diaryEntity else { return } - - delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) - } else { - isUpdate = true - delegate?.createDiaryData(text: text) - } +// if isUpdate { +// guard let diaryEntity else { return } +// +// delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) +// } else { +// isUpdate = true +// delegate?.createDiaryData(text: text) +// } } } @@ -132,12 +130,12 @@ extension DiaryDetailViewController { private func didTappedDeleteAction() { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in - if let diaryEntity = self.diaryEntity { - self.delegate?.deleteDiaryData(diaryEntity: diaryEntity) - } - - self.textView.text = "" - self.delegate?.popDiaryDetailViewController() +// if let diaryEntity = self.diaryEntity { +// self.delegate?.deleteDiaryData(diaryEntity: diaryEntity) +// } +// +// self.textView.text = "" +// self.delegate?.popDiaryDetailViewController() } showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index 82be90aa6..e59fe3d44 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -7,10 +7,8 @@ import UIKit protocol MainViewControllerDelegate: AnyObject { - func didTappedRightAddButton() - func fetchDiaryContents(mainViewController: MainViewController) - func didSelectRowAt(diaryContent: DiaryEntity) - func deleteDiaryContent(diaryContent: DiaryEntity) + func didTappedRightAddButton(newDiaryContent: DiaryContentsDTO) + func didSelectRowAt(diaryContent: DiaryContentsDTO) } final class MainViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { @@ -19,9 +17,10 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ } weak var delegate: MainViewControllerDelegate? - private var diaryContents: [DiaryEntity] + private var diaryContents: [DiaryContentsDTO]? private let dateFormatter: DateFormatter - private var diffableDatasource: UITableViewDiffableDataSource? + private let useCase: MainViewControllerUseCaseType + private var diffableDatasource: UITableViewDiffableDataSource? private lazy var tableView: UITableView = { let tableView = UITableView() @@ -32,9 +31,9 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ return tableView }() - init(diaryContents: [DiaryEntity], dateFormatter: DateFormatter) { - self.diaryContents = diaryContents + init(dateFormatter: DateFormatter, useCase: MainViewControllerUseCaseType) { self.dateFormatter = dateFormatter + self.useCase = useCase super.init(nibName: nil, bundle: nil) } @@ -55,12 +54,12 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - delegate?.fetchDiaryContents(mainViewController: self) + setUpDiaryContents() setUpTableViewDiffableDataSourceSnapShot(animated: false) } - func setUpDiaryEntity(diaryContents: [DiaryEntity]) { - self.diaryContents = diaryContents + private func setUpDiaryContents() { + diaryContents = useCase.fetchDiaryContentsDTO() } private func configureUI() { @@ -86,6 +85,8 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ // MARK: - TableView Delegate extension MainViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let diaryContents else { return } + delegate?.didSelectRowAt(diaryContent: diaryContents[indexPath.row]) tableView.deselectRow(at: indexPath, animated: true) } @@ -109,20 +110,21 @@ extension MainViewController: UITableViewDelegate { // MARK: - TableViewDiffableDataSource extension MainViewController { private func setUpTableViewDiffableDataSource() { - diffableDatasource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, diaryEntity in + diffableDatasource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] tableView, indexPath, diaryContent in guard let self = self, let cell = tableView.dequeueReusableCell(withIdentifier: MainTableViewCell.indentifier, for: indexPath) as? MainTableViewCell else { return UITableViewCell() } - let date = Date(timeIntervalSince1970: diaryEntity.date) + let date = Date(timeIntervalSince1970: diaryContent.date) let formattedDate = self.dateFormatter.string(from: date) - cell.setUpContents(title: diaryEntity.title, date: formattedDate, body: diaryEntity.body) + cell.setUpContents(title: diaryContent.title, date: formattedDate, body: diaryContent.body) return cell }) } private func setUpTableViewDiffableDataSourceSnapShot(animated: Bool = true) { - var snapShot = NSDiffableDataSourceSnapshot() + guard let diaryContents else { return } + var snapShot = NSDiffableDataSourceSnapshot() snapShot.appendSections([.main]) snapShot.appendItems(diaryContents) @@ -134,15 +136,16 @@ extension MainViewController { extension MainViewController { @objc private func didTappedRightAddButton() { - delegate?.didTappedRightAddButton() + let newDiaryContent = useCase.createNewDiary() + + delegate?.didTappedRightAddButton(newDiaryContent: newDiaryContent) } private func didTappedDeleteAction(index: Int) { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in - self.delegate?.deleteDiaryContent(diaryContent: self.diaryContents[index]) - self.diaryContents.remove(at: index) - self.setUpTableViewDiffableDataSourceSnapShot() +// self.diaryContents.remove(at: index) +// self.setUpTableViewDiffableDataSourceSnapShot() } showAlertController(title: "진짜요?", @@ -152,7 +155,9 @@ extension MainViewController { } private func didTappedShareAction(index: Int) { - let entity = self.diaryContents[index] + guard let diaryContents else { return } + + let entity = diaryContents[index] let sharedItem = entity.title + "\n" + entity.body self.showActivityViewController(items: [sharedItem as Any]) diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index fdf4a43f1..27bfb3510 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -28,8 +28,8 @@ final class AppManager { } func start() { - guard let diaryContents = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } - let mainViewController = MainViewController(diaryContents: diaryContents, dateFormatter: dateFormatter) + let useCase: MainViewControllerUseCaseType = MainViewControllerUseCase(coreDataManager: coreDataManager) + let mainViewController = MainViewController(dateFormatter: dateFormatter, useCase: useCase) mainViewController.delegate = self navigationController.viewControllers = [mainViewController] @@ -38,33 +38,22 @@ final class AppManager { // MARK: - MainViewControllerDelegate extension AppManager: MainViewControllerDelegate { - func didSelectRowAt(diaryContent: DiaryEntity) { + func didSelectRowAt(diaryContent: DiaryContentsDTO) { let date = Date(timeIntervalSince1970: diaryContent.date) let formattedDate = dateFormatter.string(from: date) - let diaryDetailViewController = DiaryDetailViewController(date: formattedDate, diaryEntity: diaryContent) + let diaryDetailViewController = DiaryDetailViewController(date: formattedDate, diaryContent: diaryContent) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) } - func didTappedRightAddButton() { + func didTappedRightAddButton(newDiaryContent: DiaryContentsDTO) { let todayDate = dateFormatter.string(from: Date()) - let diaryDetailViewController = DiaryDetailViewController(date: todayDate, isUpdate: false) + let diaryDetailViewController = DiaryDetailViewController(date: todayDate, diaryContent: newDiaryContent) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) } - - func fetchDiaryContents(mainViewController: MainViewController) { - guard let diaryContents = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return } - - mainViewController.setUpDiaryEntity(diaryContents: diaryContents) - } - - func deleteDiaryContent(diaryContent: DiaryEntity) { - coreDataManager.deleteData(entity: diaryContent) - coreDataManager.saveContext() - } } // MARK: - DiaryDetailViewControllerDelegate diff --git a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents index 1c3d18eb2..feb75f576 100644 --- a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -1,8 +1,9 @@ - + + \ No newline at end of file diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift index 1a2cc132a..cd99be1e9 100644 --- a/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataClass.swift @@ -2,7 +2,7 @@ // DiaryEntity+CoreDataClass.swift // Diary // -// Created by Hyun A Song on 2023/09/11. +// Created by Hyungmin Lee on 2023/09/14. // // diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift index 9374b2e30..7f82b3b11 100644 --- a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift @@ -2,7 +2,7 @@ // DiaryEntity+CoreDataProperties.swift // Diary // -// Created by Hyun A Song on 2023/09/11. +// Created by Hyungmin Lee on 2023/09/14. // // @@ -16,9 +16,10 @@ extension DiaryEntity { return NSFetchRequest(entityName: "DiaryEntity") } - @NSManaged public var date: Double @NSManaged public var body: String + @NSManaged public var date: Double @NSManaged public var title: String + @NSManaged public var identifier: UUID } diff --git a/Diary/Model/DTO/DiaryContentsDTO.swift b/Diary/Model/DTO/DiaryContentsDTO.swift new file mode 100644 index 000000000..4b9e26f3e --- /dev/null +++ b/Diary/Model/DTO/DiaryContentsDTO.swift @@ -0,0 +1,15 @@ +// +// DiaryContentsDTO.swift +// Diary +// +// Created by Hyungmin Lee on 2023/09/14. +// + +import Foundation + +struct DiaryContentsDTO: Hashable { + var body: String + var date: Double + var title: String + var identifier: UUID +} diff --git a/Diary/UseCase/MainViewControllerUseCase.swift b/Diary/UseCase/MainViewControllerUseCase.swift new file mode 100644 index 000000000..1d504687c --- /dev/null +++ b/Diary/UseCase/MainViewControllerUseCase.swift @@ -0,0 +1,39 @@ +// +// MainViewControllerUseCase.swift +// Diary +// +// Created by Hyungmin Lee on 2023/09/14. +// + +import Foundation + +protocol MainViewControllerUseCaseType { + func fetchDiaryContentsDTO() -> [DiaryContentsDTO]? + func createNewDiary() -> DiaryContentsDTO +} + +final class MainViewControllerUseCase: MainViewControllerUseCaseType { + private let coreDataManager: CoreDataManager + + init(coreDataManager: CoreDataManager) { + self.coreDataManager = coreDataManager + } + + func fetchDiaryContentsDTO() -> [DiaryContentsDTO]? { + guard let diaryEntity = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return nil } + + return diaryEntity.map { + DiaryContentsDTO(body: $0.body, + date: $0.date, + title: $0.title, + identifier: $0.identifier) + } + } + + func createNewDiary() -> DiaryContentsDTO { + return DiaryContentsDTO(body: "", + date: Double.zero, + title: "", + identifier: UUID()) + } +} From 575b0cd8c1763d4c35fa74bdddcdcf81d529f89f Mon Sep 17 00:00:00 2001 From: LeeZion94 Date: Thu, 14 Sep 2023 19:12:59 +0900 Subject: [PATCH 28/34] =?UTF-8?q?feat:=20DiaryDetailViewController=20UseCa?= =?UTF-8?q?se=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary.xcodeproj/project.pbxproj | 28 ++++---- .../DiaryDetailViewController.swift | 38 +++-------- Diary/Controller/MainViewController.swift | 19 +++--- Diary/Manager/AppManager.swift | 47 ++------------ Diary/Manager/CoreDataManager.swift | 23 ++++++- .../Diary.xcdatamodel/contents | 2 +- .../DiaryEntity+CoreDataProperties.swift | 3 +- ...ontentsDTO.swift => DiaryContentDTO.swift} | 4 +- .../DiaryDetailViewControllerUseCase.swift | 64 +++++++++++++++++++ Diary/UseCase/MainViewControllerUseCase.swift | 19 ++++-- 10 files changed, 145 insertions(+), 102 deletions(-) rename Diary/Model/DTO/{DiaryContentsDTO.swift => DiaryContentDTO.swift} (73%) create mode 100644 Diary/UseCase/DiaryDetailViewControllerUseCase.swift diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index eb0b848d2..6beec9245 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -11,10 +11,11 @@ 5BBC443D2A9F30ED00C528DD /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */; }; 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */; }; 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */; }; - 5BF1B2D72AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */; }; - 5BF1B2D82AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */; }; 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */; }; - 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */; }; + 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentDTO.swift */; }; + 5BF1B2E02AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DF2AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift */; }; + 5BF1B2E32AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */; }; + 5BF1B2E42AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */; }; C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE24284DF28600741E8F /* AppDelegate.swift */; }; C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE26284DF28600741E8F /* SceneDelegate.swift */; }; C739AE29284DF28600741E8F /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* MainViewController.swift */; }; @@ -32,10 +33,11 @@ 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertControllerShowable.swift; sourceTree = ""; }; 5BF1B2D32AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityViewControllerShowable.swift; sourceTree = ""; }; - 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; - 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; - 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContentsDTO.swift; sourceTree = ""; }; + 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContentDTO.swift; sourceTree = ""; }; + 5BF1B2DF2AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewControllerUseCase.swift; sourceTree = ""; }; + 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; + 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; C739AE21284DF28600741E8F /* Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diary.app; sourceTree = BUILT_PRODUCTS_DIR; }; C739AE24284DF28600741E8F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C739AE26284DF28600741E8F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -109,6 +111,7 @@ isa = PBXGroup; children = ( 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */, + 5BF1B2DF2AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift */, ); path = UseCase; sourceTree = ""; @@ -116,7 +119,7 @@ 5BF1B2DC2AB2DA7D00FDC1A5 /* DTO */ = { isa = PBXGroup; children = ( - 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift */, + 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentDTO.swift */, ); path = DTO; sourceTree = ""; @@ -158,8 +161,8 @@ isa = PBXGroup; children = ( C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, - 5BF1B2D52AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift */, - 5BF1B2D62AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift */, + 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */, + 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */, ); path = CoreData; sourceTree = ""; @@ -276,18 +279,19 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5BF1B2D72AB2D94700FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */, + 5BF1B2E42AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */, 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */, 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */, C739AE29284DF28600741E8F /* MainViewController.swift in Sources */, + 5BF1B2E32AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, - 5BF1B2D82AB2D94700FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */, + 5BF1B2E02AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, - 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentsDTO.swift in Sources */, + 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentDTO.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */, diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index b4da32ba1..208dd5c95 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -8,9 +8,6 @@ import UIKit protocol DiaryDetailViewControllerDelegate: AnyObject { - func createDiaryData(text: String) - func updateDiaryData(diaryEntity: DiaryEntity, text: String) - func deleteDiaryData(diaryEntity: DiaryEntity) func popDiaryDetailViewController() } @@ -25,13 +22,13 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable return textView }() - private var diaryContent: DiaryContentsDTO private let date: String + private let useCase: DiaryDetailViewControllerUseCaseType weak var delegate: DiaryDetailViewControllerDelegate? - init(date: String, diaryContent: DiaryContentsDTO) { + init(date: String, useCase: DiaryDetailViewControllerUseCaseType) { self.date = date - self.diaryContent = diaryContent + self.useCase = useCase super.init(nibName: nil, bundle: nil) } @@ -75,18 +72,16 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable ]) } + private func setUpText() { + textView.text = useCase.setUpTextFromDiaryContentDTO() + } + private func setUpViewController() { view.backgroundColor = .systemBackground navigationItem.title = date navigationItem.rightBarButtonItem = .init(title: "더보기", style: .plain, target: self, action: #selector(didTappedMoreButton)) } - private func setUpText() { -// guard let diaryEntity else { return } -// -// textView.text = diaryEntity.title + "\n" + diaryEntity.body - } - private func addObserver() { NotificationCenter.default.addObserver(self, selector: #selector(saveDiaryContents), name: UIApplication.didEnterBackgroundNotification, object: nil) } @@ -97,16 +92,7 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable @objc private func saveDiaryContents() { - let text = textView.text ?? "" - -// if isUpdate { -// guard let diaryEntity else { return } -// -// delegate?.updateDiaryData(diaryEntity: diaryEntity, text: text) -// } else { -// isUpdate = true -// delegate?.createDiaryData(text: text) -// } + useCase.upsert(diaryDetailContent: textView.text) } } @@ -130,12 +116,8 @@ extension DiaryDetailViewController { private func didTappedDeleteAction() { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in -// if let diaryEntity = self.diaryEntity { -// self.delegate?.deleteDiaryData(diaryEntity: diaryEntity) -// } -// -// self.textView.text = "" -// self.delegate?.popDiaryDetailViewController() + self.useCase.deleteDiary() + self.delegate?.popDiaryDetailViewController() } showAlertController(title: "진짜요?", message: "정말로 삭제하시겠어요?", style: .alert, actions: [cancelAction, deleteAction]) diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index e59fe3d44..4e8f6f4cb 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -7,8 +7,8 @@ import UIKit protocol MainViewControllerDelegate: AnyObject { - func didTappedRightAddButton(newDiaryContent: DiaryContentsDTO) - func didSelectRowAt(diaryContent: DiaryContentsDTO) + func didTappedRightAddButton(newDiaryContent: DiaryContentDTO) + func didSelectRowAt(diaryContent: DiaryContentDTO) } final class MainViewController: UIViewController, AlertControllerShowable, ActivityViewControllerShowable { @@ -17,10 +17,10 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ } weak var delegate: MainViewControllerDelegate? - private var diaryContents: [DiaryContentsDTO]? + private var diaryContents: [DiaryContentDTO]? private let dateFormatter: DateFormatter private let useCase: MainViewControllerUseCaseType - private var diffableDatasource: UITableViewDiffableDataSource? + private var diffableDatasource: UITableViewDiffableDataSource? private lazy var tableView: UITableView = { let tableView = UITableView() @@ -59,7 +59,7 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ } private func setUpDiaryContents() { - diaryContents = useCase.fetchDiaryContentsDTO() + diaryContents = useCase.fetchDiaryContentDTO() } private func configureUI() { @@ -124,7 +124,7 @@ extension MainViewController { private func setUpTableViewDiffableDataSourceSnapShot(animated: Bool = true) { guard let diaryContents else { return } - var snapShot = NSDiffableDataSourceSnapshot() + var snapShot = NSDiffableDataSourceSnapshot() snapShot.appendSections([.main]) snapShot.appendItems(diaryContents) @@ -144,8 +144,11 @@ extension MainViewController { private func didTappedDeleteAction(index: Int) { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in -// self.diaryContents.remove(at: index) -// self.setUpTableViewDiffableDataSourceSnapShot() + guard let deleteDiary = self.diaryContents?[index] else { return } + + self.useCase.deleteDiary(deleteDiaryId: deleteDiary.identifier) + self.diaryContents?.remove(at: index) + self.setUpTableViewDiffableDataSourceSnapShot() } showAlertController(title: "진짜요?", diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 27bfb3510..1f24263fb 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -11,10 +11,8 @@ final class AppManager { private let navigationController: UINavigationController private let dateFormatter: DateFormatter = { let dateFormatter = DateFormatter() - let localeID = Locale.preferredLanguages.first ?? "kr_KR" - let deviceLocale = Locale(identifier: localeID).languageCode ?? "KST" - dateFormatter.locale = Locale(identifier: deviceLocale) + dateFormatter.locale = Locale.current dateFormatter.timeZone = TimeZone.current dateFormatter.dateStyle = .long return dateFormatter @@ -38,18 +36,20 @@ final class AppManager { // MARK: - MainViewControllerDelegate extension AppManager: MainViewControllerDelegate { - func didSelectRowAt(diaryContent: DiaryContentsDTO) { + func didSelectRowAt(diaryContent: DiaryContentDTO) { let date = Date(timeIntervalSince1970: diaryContent.date) let formattedDate = dateFormatter.string(from: date) - let diaryDetailViewController = DiaryDetailViewController(date: formattedDate, diaryContent: diaryContent) + let useCase: DiaryDetailViewControllerUseCaseType = DiaryDetailViewControllerUseCase(coreDataManager: coreDataManager, diaryContent: diaryContent) + let diaryDetailViewController = DiaryDetailViewController(date: formattedDate, useCase: useCase) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) } - func didTappedRightAddButton(newDiaryContent: DiaryContentsDTO) { + func didTappedRightAddButton(newDiaryContent: DiaryContentDTO) { let todayDate = dateFormatter.string(from: Date()) - let diaryDetailViewController = DiaryDetailViewController(date: todayDate, diaryContent: newDiaryContent) + let useCase: DiaryDetailViewControllerUseCaseType = DiaryDetailViewControllerUseCase(coreDataManager: coreDataManager, diaryContent: newDiaryContent) + let diaryDetailViewController = DiaryDetailViewController(date: todayDate, useCase: useCase) diaryDetailViewController.delegate = self navigationController.pushViewController(diaryDetailViewController, animated: true) @@ -58,40 +58,7 @@ extension AppManager: MainViewControllerDelegate { // MARK: - DiaryDetailViewControllerDelegate extension AppManager: DiaryDetailViewControllerDelegate { - func createDiaryData(text: String) { - guard let (title, body) = convertDiaryData(text: text) else { return } - let date = Date().timeIntervalSince1970 - let diaryEntityProperties: [String: Any] = ["title": title, "body": body, "date": date] - - coreDataManager.insertData(entityName: "DiaryEntity", entityProperties: diaryEntityProperties) - coreDataManager.saveContext() - } - - func updateDiaryData(diaryEntity: DiaryEntity, text: String) { - guard let (title, body) = convertDiaryData(text: text) else { return } - let date = Date().timeIntervalSince1970 - - diaryEntity.title = title - diaryEntity.body = body - diaryEntity.date = date - coreDataManager.saveContext() - } - - func deleteDiaryData(diaryEntity: DiaryEntity) { - coreDataManager.deleteData(entity: diaryEntity) - } - func popDiaryDetailViewController() { navigationController.popViewController(animated: true) } - - private func convertDiaryData(text: String) -> (String, String)? { - let separatedText = text.split(separator: "\n", maxSplits: 1) - guard let titleText = separatedText.first?.description else { return nil } - - let removedTitleText = separatedText.dropFirst() - let bodyText = removedTitleText.count != 0 ? removedTitleText.description : "" - - return (titleText, bodyText) - } } diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index 1f37c49f6..728c5187c 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -38,8 +38,20 @@ class CoreDataManager { } } - func deleteData(entity: NSManagedObject) { - context.delete(entity) + func updateData(request: NSFetchRequest, entityProperties: [String: Any]) where T.ID == UUID { + guard let dataList = try? context.fetch(request), let id = entityProperties["id"] as? UUID else { return } + guard let updateObject = dataList.filter({ $0.id == id}).first as? NSManagedObject else { return } + + for entityProperty in entityProperties { + updateObject.setValue(entityProperty.value, forKey: entityProperty.key) + } + } + + func deleteData(request: NSFetchRequest, identifier: UUID) where T.ID == UUID { + guard let dataList = try? context.fetch(request) else { return } + guard let deleteObject = dataList.filter({ $0.id == identifier}).first as? NSManagedObject else { return } + + context.delete(deleteObject) } func saveContext () { @@ -52,4 +64,11 @@ class CoreDataManager { } } } + + func isExistData(request: NSFetchRequest, identifier: UUID) -> Bool where T.ID == UUID { + guard let dataList = try? context.fetch(request) else { return false } + guard let data = dataList.filter({ $0.id == identifier}).first as? NSManagedObject else { return false } + + return true + } } diff --git a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents index feb75f576..ca3458ddd 100644 --- a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift index 7f82b3b11..f1f238a9f 100644 --- a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift @@ -19,8 +19,7 @@ extension DiaryEntity { @NSManaged public var body: String @NSManaged public var date: Double @NSManaged public var title: String - @NSManaged public var identifier: UUID - + @NSManaged public var id: UUID } extension DiaryEntity: Identifiable { diff --git a/Diary/Model/DTO/DiaryContentsDTO.swift b/Diary/Model/DTO/DiaryContentDTO.swift similarity index 73% rename from Diary/Model/DTO/DiaryContentsDTO.swift rename to Diary/Model/DTO/DiaryContentDTO.swift index 4b9e26f3e..e140041b4 100644 --- a/Diary/Model/DTO/DiaryContentsDTO.swift +++ b/Diary/Model/DTO/DiaryContentDTO.swift @@ -1,5 +1,5 @@ // -// DiaryContentsDTO.swift +// DiaryContentDTO.swift // Diary // // Created by Hyungmin Lee on 2023/09/14. @@ -7,7 +7,7 @@ import Foundation -struct DiaryContentsDTO: Hashable { +struct DiaryContentDTO: Hashable { var body: String var date: Double var title: String diff --git a/Diary/UseCase/DiaryDetailViewControllerUseCase.swift b/Diary/UseCase/DiaryDetailViewControllerUseCase.swift new file mode 100644 index 000000000..4aae15aff --- /dev/null +++ b/Diary/UseCase/DiaryDetailViewControllerUseCase.swift @@ -0,0 +1,64 @@ +// +// DiaryDetailViewControllerUseCase.swift +// Diary +// +// Created by Hyungmin Lee on 2023/09/14. +// + +import Foundation + +protocol DiaryDetailViewControllerUseCaseType { + func setUpTextFromDiaryContentDTO() -> String + func upsert(diaryDetailContent: String) + func deleteDiary() +} + +final class DiaryDetailViewControllerUseCase: DiaryDetailViewControllerUseCaseType { + private let coreDataManager: CoreDataManager + private let diaryContent: DiaryContentDTO + + init(coreDataManager: CoreDataManager, diaryContent: DiaryContentDTO) { + self.coreDataManager = coreDataManager + self.diaryContent = diaryContent + } + + func setUpTextFromDiaryContentDTO() -> String { + if diaryContent.title.count == 0 && diaryContent.body.count == 0 { + return "" + } + + return diaryContent.title + "\n" + diaryContent.body + } + + func upsert(diaryDetailContent: String) { + guard let (title, body) = convertDiaryData(text: diaryDetailContent) else { return } + let isExistDiary = coreDataManager.isExistData(request: DiaryEntity.fetchRequest(), identifier: diaryContent.identifier) + let diaryEntityProperty: [String: Any] = ["title": title, + "body": body, + "date": Date().timeIntervalSince1970, + "id": diaryContent.identifier] + if isExistDiary { + coreDataManager.updateData(request: DiaryEntity.fetchRequest(), entityProperties: diaryEntityProperty) + } else { + coreDataManager.insertData(entityName: "DiaryEntity", entityProperties: diaryEntityProperty) + } + } + + func deleteDiary() { + coreDataManager.deleteData(request: DiaryEntity.fetchRequest(), identifier: diaryContent.identifier) + } +} + +// MARK: - Private +extension DiaryDetailViewControllerUseCase { + private func convertDiaryData(text: String) -> (String, String)? { + let separatedText = text.split(separator: "\n", maxSplits: 1) + guard let titleText = separatedText.first?.description else { return nil } + + if let bodyText = separatedText.dropFirst().first { + return (titleText, String(describing: bodyText)) + } + + return (titleText, "") + } +} diff --git a/Diary/UseCase/MainViewControllerUseCase.swift b/Diary/UseCase/MainViewControllerUseCase.swift index 1d504687c..e9d40c277 100644 --- a/Diary/UseCase/MainViewControllerUseCase.swift +++ b/Diary/UseCase/MainViewControllerUseCase.swift @@ -8,8 +8,9 @@ import Foundation protocol MainViewControllerUseCaseType { - func fetchDiaryContentsDTO() -> [DiaryContentsDTO]? - func createNewDiary() -> DiaryContentsDTO + func fetchDiaryContentDTO() -> [DiaryContentDTO]? + func createNewDiary() -> DiaryContentDTO + func deleteDiary(deleteDiaryId: UUID) } final class MainViewControllerUseCase: MainViewControllerUseCaseType { @@ -19,21 +20,25 @@ final class MainViewControllerUseCase: MainViewControllerUseCaseType { self.coreDataManager = coreDataManager } - func fetchDiaryContentsDTO() -> [DiaryContentsDTO]? { + func fetchDiaryContentDTO() -> [DiaryContentDTO]? { guard let diaryEntity = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return nil } return diaryEntity.map { - DiaryContentsDTO(body: $0.body, + DiaryContentDTO(body: $0.body, date: $0.date, title: $0.title, - identifier: $0.identifier) + identifier: $0.id) } } - func createNewDiary() -> DiaryContentsDTO { - return DiaryContentsDTO(body: "", + func createNewDiary() -> DiaryContentDTO { + return DiaryContentDTO(body: "", date: Double.zero, title: "", identifier: UUID()) } + + func deleteDiary(deleteDiaryId: UUID) { + coreDataManager.deleteData(request: DiaryEntity.fetchRequest(), identifier: deleteDiaryId) + } } From 258deca23335219dcd9dda51eab61f9f58600ff1 Mon Sep 17 00:00:00 2001 From: LeeZion94 Date: Thu, 14 Sep 2023 19:22:11 +0900 Subject: [PATCH 29/34] =?UTF-8?q?feat:=20=EB=88=84=EB=9D=BD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/CoreDataManager.swift | 4 ++-- Diary/UseCase/MainViewControllerUseCase.swift | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index 728c5187c..39fb4f3fd 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -7,9 +7,9 @@ import CoreData -class CoreDataManager { +final class CoreDataManager { private let name: String - lazy var context = persistentContainer.viewContext + private lazy var context = persistentContainer.viewContext private lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: name) diff --git a/Diary/UseCase/MainViewControllerUseCase.swift b/Diary/UseCase/MainViewControllerUseCase.swift index e9d40c277..cbde2cf2a 100644 --- a/Diary/UseCase/MainViewControllerUseCase.swift +++ b/Diary/UseCase/MainViewControllerUseCase.swift @@ -21,7 +21,10 @@ final class MainViewControllerUseCase: MainViewControllerUseCaseType { } func fetchDiaryContentDTO() -> [DiaryContentDTO]? { - guard let diaryEntity = try? coreDataManager.fetchData(request: DiaryEntity.fetchRequest()) else { return nil } + let fetchRequest = DiaryEntity.fetchRequest() + + fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] + guard let diaryEntity = try? coreDataManager.fetchData(request: fetchRequest) else { return nil } return diaryEntity.map { DiaryContentDTO(body: $0.body, From 12cccf3d252871f5981144b9f9d67061afd89884 Mon Sep 17 00:00:00 2001 From: LeeZion94 Date: Thu, 14 Sep 2023 21:04:54 +0900 Subject: [PATCH 30/34] =?UTF-8?q?feat:=20CoreDataManagerType=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .swiftlint.yml | 1 + Diary.xcodeproj/project.pbxproj | 30 ++++++++-------- Diary/App/SceneDelegate.swift | 5 ++- Diary/Manager/AppManager.swift | 4 +-- Diary/Manager/CoreDataManager.swift | 34 ++++++++++++++----- .../Diary.xcdatamodeld/.xccurrentversion | 8 ----- .../Diary.xcdatamodel/contents | 8 ++--- .../DiaryEntity+CoreDataProperties.swift | 7 ++-- .../DiaryDetailViewControllerUseCase.swift | 4 +-- Diary/UseCase/MainViewControllerUseCase.swift | 4 +-- 10 files changed, 57 insertions(+), 48 deletions(-) delete mode 100644 Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion diff --git a/.swiftlint.yml b/.swiftlint.yml index 1b601d3fa..32e5c4a92 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -2,3 +2,4 @@ disabled_rules: - line_length - vertical_whitespace - trailing_whitespace +- type_name diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 6beec9245..a492b6ad4 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 5B2E75E42AB322D7004D828F /* Diary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 5B2E75E22AB322D7004D828F /* Diary.xcdatamodeld */; }; + 5B2E75EB2AB323F3004D828F /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2E75E92AB323F3004D828F /* DiaryEntity+CoreDataClass.swift */; }; + 5B2E75EC2AB323F3004D828F /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2E75EA2AB323F3004D828F /* DiaryEntity+CoreDataProperties.swift */; }; 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */; }; 5BBC443D2A9F30ED00C528DD /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */; }; 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */; }; @@ -14,12 +17,9 @@ 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */; }; 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentDTO.swift */; }; 5BF1B2E02AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2DF2AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift */; }; - 5BF1B2E32AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */; }; - 5BF1B2E42AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */; }; C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE24284DF28600741E8F /* AppDelegate.swift */; }; C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE26284DF28600741E8F /* SceneDelegate.swift */; }; C739AE29284DF28600741E8F /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C739AE28284DF28600741E8F /* MainViewController.swift */; }; - C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */; }; C739AE31284DF28600741E8F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C739AE30284DF28600741E8F /* Assets.xcassets */; }; C739AE34284DF28600741E8F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C739AE32284DF28600741E8F /* LaunchScreen.storyboard */; }; D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2BCA2B42AAF3B1500D55F4C /* CoreDataManager.swift */; }; @@ -29,6 +29,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 5B2E75E32AB322D7004D828F /* Diary.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Diary.xcdatamodel; sourceTree = ""; }; + 5B2E75E92AB323F3004D828F /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; + 5B2E75EA2AB323F3004D828F /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; 5BBC44382A9F036000C528DD /* MainTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTableViewCell.swift; sourceTree = ""; }; 5BBC443C2A9F30ED00C528DD /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; 5BF1B2D12AAF422300FDC1A5 /* AlertControllerShowable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertControllerShowable.swift; sourceTree = ""; }; @@ -36,13 +39,10 @@ 5BF1B2D92AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewControllerUseCase.swift; sourceTree = ""; }; 5BF1B2DD2AB2DA8800FDC1A5 /* DiaryContentDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryContentDTO.swift; sourceTree = ""; }; 5BF1B2DF2AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailViewControllerUseCase.swift; sourceTree = ""; }; - 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataClass.swift"; sourceTree = ""; }; - 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiaryEntity+CoreDataProperties.swift"; sourceTree = ""; }; C739AE21284DF28600741E8F /* Diary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diary.app; sourceTree = BUILT_PRODUCTS_DIR; }; C739AE24284DF28600741E8F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C739AE26284DF28600741E8F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; C739AE28284DF28600741E8F /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; - C739AE2E284DF28600741E8F /* Diary.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Diary.xcdatamodel; sourceTree = ""; }; C739AE30284DF28600741E8F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C739AE33284DF28600741E8F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; C739AE35284DF28600741E8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -160,9 +160,9 @@ D2BCA2B22AAF3A8700D55F4C /* CoreData */ = { isa = PBXGroup; children = ( - C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */, - 5BF1B2E12AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift */, - 5BF1B2E22AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift */, + 5B2E75E22AB322D7004D828F /* Diary.xcdatamodeld */, + 5B2E75E92AB323F3004D828F /* DiaryEntity+CoreDataClass.swift */, + 5B2E75EA2AB323F3004D828F /* DiaryEntity+CoreDataProperties.swift */, ); path = CoreData; sourceTree = ""; @@ -279,20 +279,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5BF1B2E42AB2F02D00FDC1A5 /* DiaryEntity+CoreDataProperties.swift in Sources */, + 5B2E75EC2AB323F3004D828F /* DiaryEntity+CoreDataProperties.swift in Sources */, 5BF1B2D42AAF42FB00FDC1A5 /* ActivityViewControllerShowable.swift in Sources */, 5BF1B2D22AAF422300FDC1A5 /* AlertControllerShowable.swift in Sources */, C739AE29284DF28600741E8F /* MainViewController.swift in Sources */, - 5BF1B2E32AB2F02D00FDC1A5 /* DiaryEntity+CoreDataClass.swift in Sources */, + 5B2E75EB2AB323F3004D828F /* DiaryEntity+CoreDataClass.swift in Sources */, C739AE25284DF28600741E8F /* AppDelegate.swift in Sources */, 5BF1B2E02AB2EAC800FDC1A5 /* DiaryDetailViewControllerUseCase.swift in Sources */, C739AE27284DF28600741E8F /* SceneDelegate.swift in Sources */, D2C1FBF32A9F0A0900526DA5 /* DiaryDetailViewController.swift in Sources */, - C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, D2BCA2B52AAF3B1500D55F4C /* CoreDataManager.swift in Sources */, 5BBC44392A9F036000C528DD /* MainTableViewCell.swift in Sources */, 5BF1B2DE2AB2DA8800FDC1A5 /* DiaryContentDTO.swift in Sources */, D2C1FBF62A9F1EC100526DA5 /* AppManager.swift in Sources */, + 5B2E75E42AB322D7004D828F /* Diary.xcdatamodeld in Sources */, D2DB46872AA1A83B009D1926 /* ReuseIdentifiable.swift in Sources */, 5BF1B2DA2AB2D9E000FDC1A5 /* MainViewControllerUseCase.swift in Sources */, ); @@ -506,12 +506,12 @@ /* End XCConfigurationList section */ /* Begin XCVersionGroup section */ - C739AE2D284DF28600741E8F /* Diary.xcdatamodeld */ = { + 5B2E75E22AB322D7004D828F /* Diary.xcdatamodeld */ = { isa = XCVersionGroup; children = ( - C739AE2E284DF28600741E8F /* Diary.xcdatamodel */, + 5B2E75E32AB322D7004D828F /* Diary.xcdatamodel */, ); - currentVersion = C739AE2E284DF28600741E8F /* Diary.xcdatamodel */; + currentVersion = 5B2E75E32AB322D7004D828F /* Diary.xcdatamodel */; path = Diary.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/Diary/App/SceneDelegate.swift b/Diary/App/SceneDelegate.swift index 5e0f8ab51..c79764cbd 100644 --- a/Diary/App/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -12,11 +12,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 navigationController = UINavigationController() - let coreDataManager = CoreDataManager(name: "Diary") + let diaryCoreDataManager: any CoreDataManagerType = CoreDataManager(name: "Diary") - appManager = AppManager(navigationController: navigationController, coreDataManager: coreDataManager) + appManager = AppManager(navigationController: navigationController, coreDataManager: diaryCoreDataManager) appManager?.start() window = UIWindow(windowScene: windowScene) window?.rootViewController = navigationController diff --git a/Diary/Manager/AppManager.swift b/Diary/Manager/AppManager.swift index 1f24263fb..c9ba3580b 100644 --- a/Diary/Manager/AppManager.swift +++ b/Diary/Manager/AppManager.swift @@ -18,9 +18,9 @@ final class AppManager { return dateFormatter }() - private let coreDataManager: CoreDataManager + private let coreDataManager: any CoreDataManagerType - init(navigationController: UINavigationController, coreDataManager: CoreDataManager) { + init(navigationController: UINavigationController, coreDataManager: any CoreDataManagerType) { self.navigationController = navigationController self.coreDataManager = coreDataManager } diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index 39fb4f3fd..1e3003c99 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -7,7 +7,17 @@ import CoreData -final class CoreDataManager { +protocol CoreDataManagerType { + associatedtype T + + func fetchData(request: NSFetchRequest) throws -> [T] + func insertData(entityName: String, entityProperties: [String: Any]) + func updateData(request: NSFetchRequest, entityProperties: [String: Any]) where T.ID == UUID + func deleteData(request: NSFetchRequest, identifier: UUID) where T.ID == UUID + func isExistData(request: NSFetchRequest, identifier: UUID) -> Bool where T.ID == UUID +} + +final class CoreDataManager: CoreDataManagerType { private let name: String private lazy var context = persistentContainer.viewContext @@ -35,6 +45,8 @@ final class CoreDataManager { for entityProperty in entityProperties { managedObject.setValue(entityProperty.value, forKey: entityProperty.key) } + + saveContext() } } @@ -45,6 +57,8 @@ final class CoreDataManager { for entityProperty in entityProperties { updateObject.setValue(entityProperty.value, forKey: entityProperty.key) } + + saveContext() } func deleteData(request: NSFetchRequest, identifier: UUID) where T.ID == UUID { @@ -52,9 +66,17 @@ final class CoreDataManager { guard let deleteObject = dataList.filter({ $0.id == identifier}).first as? NSManagedObject else { return } context.delete(deleteObject) + saveContext() + } + + func isExistData(request: NSFetchRequest, identifier: UUID) -> Bool where T.ID == UUID { + guard let dataList = try? context.fetch(request) else { return false } + guard let data = dataList.filter({ $0.id == identifier}).first as? NSManagedObject else { return false } + + return true } - func saveContext () { + private func saveContext () { if context.hasChanges { do { try context.save() @@ -64,11 +86,5 @@ final class CoreDataManager { } } } - - func isExistData(request: NSFetchRequest, identifier: UUID) -> Bool where T.ID == UUID { - guard let dataList = try? context.fetch(request) else { return false } - guard let data = dataList.filter({ $0.id == identifier}).first as? NSManagedObject else { return false } - - return true - } + } diff --git a/Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion b/Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion deleted file mode 100644 index d49fecccc..000000000 --- a/Diary/Model/CoreData/Diary.xcdatamodeld/.xccurrentversion +++ /dev/null @@ -1,8 +0,0 @@ - - - - - _XCCurrentVersionName - Diary.xcdatamodel - - diff --git a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents index ca3458ddd..3436163cf 100644 --- a/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ b/Diary/Model/CoreData/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -1,9 +1,9 @@ - - - - + + + + \ No newline at end of file diff --git a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift index f1f238a9f..c41eb45f5 100644 --- a/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift +++ b/Diary/Model/CoreData/DiaryEntity+CoreDataProperties.swift @@ -16,12 +16,13 @@ extension DiaryEntity { return NSFetchRequest(entityName: "DiaryEntity") } + @NSManaged public var id: UUID + @NSManaged public var title: String @NSManaged public var body: String @NSManaged public var date: Double - @NSManaged public var title: String - @NSManaged public var id: UUID + } -extension DiaryEntity: Identifiable { +extension DiaryEntity : Identifiable { } diff --git a/Diary/UseCase/DiaryDetailViewControllerUseCase.swift b/Diary/UseCase/DiaryDetailViewControllerUseCase.swift index 4aae15aff..1b9802224 100644 --- a/Diary/UseCase/DiaryDetailViewControllerUseCase.swift +++ b/Diary/UseCase/DiaryDetailViewControllerUseCase.swift @@ -14,10 +14,10 @@ protocol DiaryDetailViewControllerUseCaseType { } final class DiaryDetailViewControllerUseCase: DiaryDetailViewControllerUseCaseType { - private let coreDataManager: CoreDataManager + private let coreDataManager: any CoreDataManagerType private let diaryContent: DiaryContentDTO - init(coreDataManager: CoreDataManager, diaryContent: DiaryContentDTO) { + init(coreDataManager: any CoreDataManagerType, diaryContent: DiaryContentDTO) { self.coreDataManager = coreDataManager self.diaryContent = diaryContent } diff --git a/Diary/UseCase/MainViewControllerUseCase.swift b/Diary/UseCase/MainViewControllerUseCase.swift index cbde2cf2a..025f8df37 100644 --- a/Diary/UseCase/MainViewControllerUseCase.swift +++ b/Diary/UseCase/MainViewControllerUseCase.swift @@ -14,9 +14,9 @@ protocol MainViewControllerUseCaseType { } final class MainViewControllerUseCase: MainViewControllerUseCaseType { - private let coreDataManager: CoreDataManager + private let coreDataManager: any CoreDataManagerType - init(coreDataManager: CoreDataManager) { + init(coreDataManager: any CoreDataManagerType) { self.coreDataManager = coreDataManager } From 0d8b23d7a71cef8888bd82422bca4c9f5d3bbdaf Mon Sep 17 00:00:00 2001 From: LeeZion94 Date: Thu, 14 Sep 2023 21:24:01 +0900 Subject: [PATCH 31/34] =?UTF-8?q?fix:=20Save=20=EC=8B=9C=20Fetch=20?= =?UTF-8?q?=ED=83=80=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 3 +-- Diary/Controller/MainViewController.swift | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 208dd5c95..57959958e 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -55,7 +55,6 @@ final class DiaryDetailViewController: UIViewController, AlertControllerShowable override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - saveDiaryContents() removeObserver() } @@ -126,7 +125,7 @@ extension DiaryDetailViewController { private func didTappedShareAction() { let sharedItem = self.textView.text - self.showActivityViewController(items: [sharedItem as Any]) + showActivityViewController(items: [sharedItem as Any]) } } diff --git a/Diary/Controller/MainViewController.swift b/Diary/Controller/MainViewController.swift index 4e8f6f4cb..3ca2d9bb7 100644 --- a/Diary/Controller/MainViewController.swift +++ b/Diary/Controller/MainViewController.swift @@ -51,8 +51,8 @@ final class MainViewController: UIViewController, AlertControllerShowable, Activ setUpTableViewDiffableDataSource() } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) setUpDiaryContents() setUpTableViewDiffableDataSourceSnapShot(animated: false) From ed70720fa4c204c70d92308fa5b984e9eae65489 Mon Sep 17 00:00:00 2001 From: LeeZion94 Date: Thu, 14 Sep 2023 21:32:25 +0900 Subject: [PATCH 32/34] =?UTF-8?q?fix:=20Delete=EA=B0=80=20=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Controller/DiaryDetailViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Diary/Controller/DiaryDetailViewController.swift b/Diary/Controller/DiaryDetailViewController.swift index 57959958e..c59575232 100644 --- a/Diary/Controller/DiaryDetailViewController.swift +++ b/Diary/Controller/DiaryDetailViewController.swift @@ -115,6 +115,7 @@ extension DiaryDetailViewController { private func didTappedDeleteAction() { let cancelAction = UIAlertAction(title: "취소", style: .cancel) let deleteAction = UIAlertAction(title: "삭제", style: .destructive) { _ in + self.textView.text = "" self.useCase.deleteDiary() self.delegate?.popDiaryDetailViewController() } From c5a27c229e06fbc9fe8302d84bf0f468e5b56248 Mon Sep 17 00:00:00 2001 From: serena <101619749+serena0720@users.noreply.github.com> Date: Fri, 15 Sep 2023 16:12:17 +0900 Subject: [PATCH 33/34] =?UTF-8?q?docs:=20Step2=20README=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 100 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 98112b9ef..599850a42 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ 나만의 일기를 작성해보세요✏️ - - 주요 개념: UITableViewDiffableDataSource, TextView, Keyboard Layout, DateFormatter, AppManager + - 주요 개념: UITableViewDiffableDataSource, TextView, Keyboard Layout, DateFormatter, AppManager, CoreData, ActivityViewController, AlertController
@@ -46,24 +46,30 @@ |:---:|---| | **2023.08.29** |▫️ Prototype 구현
| | **2023.08.30** |▫️ Lint 적용
▫️ MainVC에 TableView 및 TableViewCell 코드 구현
▫️ AddDiaryVC에 TextView 코드 구현
▫️ DiarySample JSON 모델 추가
▫️ TableViewDiffableDataSource 적용
▫️ DateFormatter에 Localization 적용
▫️ AppManager 구현
▫️ 순환참조 제거
| - +| **2023.09.01** |▫️ ReuseIdentifiable 프로토콜 구현
▫️ CompressionPriority, HuggingPriority를 setUpConstriants로 위치 변경
| +| **2023.09.06** |▫️ CoreData과 DiaryCoreData 생성 및 CRUD 구현
▫️ ActivityViewControllerShowable, AlertControllerShowable 타입 구현
▫️ ViewController에 Showable Type 적용| +| **2023.09.07** |▫️ AppManager에 DiaryDataManager 주입
▫️ DiarySample 삭제 및 DiaryEntity 타입 적용
| +| **2023.09.12** |▫️ viewWillAppear 시 dataFetch
▫️ DiaryDetailViewController Update, Delete 구현
▫️ TextView EndEditing 시, background 시 Save로직 추가
▫️ NotificationCenter Observer 등록
▫️ diffableDataSource delete시 bottom Constraint 충돌해결
▫️ 사용하지 않는 model 삭제
| +| **2023.09.14** |▫️ title만 존재할경우 body도 title처럼 나오는 이슈 수정
▫️ insertData로직 추가 및 data Create반환 값 삭제, DiaryCoreDataManager 삭제
▫️ insertData 에러 수정
▫️ CoreData 수정 및 DiaryContentsDTO 생성
▫️ DiaryDetailViewController UseCase 생성 및 적용
▫️ CoreDataManagerType 생성 및 적용
▫️ Save, Delete 시 에러 수정|
## 4. 📊 다이어그램 - -> 추후 작성 예정 +
## 5. 📲 실행 화면 -| 다이어리 화면 구동 | 다이어리 편집 시 키보드 동작 | -| :--------------: | :-------: | -| | | - +| 다이어리 화면 구동 | 다이어리 편집 시 키보드 동작 | 다이어리 생성 | +| :--------------: | :-------: | :-------: | +| | | | +| **선택 시 편집화면 이동** | **다이어리 화면 share** | **다이어리 화면 delete** | +| | | | + | **다이어리 편집 시 Backgound 저장** | **다이어리 편집 화면 share** | **다이어리 편집 화면 delete**| + | | | |
@@ -119,6 +125,79 @@ <정리 자료> [Compression Resistance Priority](https://medium.com/@LeeZion94/compressionresistance-priority-d17c6f407b7f) [Hugging Priority](https://medium.com/@LeeZion94/uistackview-alignment-fill-hugging-84af069eb694) + +
+ +### 🔥 ViewController에서의 DiaryCoreDataManager에 대한 의존성 +- ViewController(이하 VC)는 VC를 띄우는 데 있어서 필요한 데이터가 아닌 다른 것들을 의존하게 된다면 재사용성이 많이 떨어질 수 밖에 없다고 생각합니다. 따라서 이를 위해 상위 타입인 AppManager를 만들게 되었습니다. + + 하지만 과제를 추가적으로 진행해나가면서 VC에 진입할 때 마다 fetch한 데이터를 갱신하고, Delete기능들 등이 추가되면서 DiaryCoreDataManager를 직접적으로 VC에서 주입했다면 재사용성은 떨어져도 코드의 가독성 및 이후의 유지 보수 관련해서는 더 쉽게 이해할 수 있는 코드가 되지않을까? 라고 생각했습니다. 그렇게 생각한 이유는 DiaryCoreDataManager를 주입받지 않았을 때 발생하는 AppManager와의 많은 소통때문이라고 생각합니다. 따라서 ViewController의 재사용성을 살리면서 불필요하게 많아진 상위 타입으로의 소통을 변경할 수 있는 방법을 생각해봐야했습니다. + +- UseCase Type을 만들어서 위와 같은 문제점을 해결할 수 있었습니다. +ViewController에서 View를 띄우는 로직 및 이벤트를 받아 처리하는 로직 이외의 모든 로직을 UseCase로 넘겨주어 처리하게 했습니다. 따라서 UseCase가 DiaryCoreDataManager를 주입받아 CRUD를 담당하는 기능들을 처리할 수 있도록 했고 이에 따라 ViewController에서는 상위 타입과 소통을 하는 것이 아닌 ViewController에서 가지고 있는 UseCase와 소통함에 따라 의사소통 방식의 개선으로 인해 가독성이 상승했습니다. +또한, ViewController에서는 View를 띄우거나, 사용자로부터 이벤트를 받아 처리하는 로직외의 모든 부분들을 UseCase에서 담당하게 되면서 ViewController의 재사용성도 챙길 수 있게 되었습니다. + +
+ +### 🔥 TableView delete 한 후 Scroll할 때의 Constraint 충돌 +- 현재 TableView에서는 DiffableDataSource을 활용하여 Cell을 관리하고 있습니다. Cell을 Swipe 했을 때 존재하는 Delete 기능을 사용하여 Cell을 삭제하고 스크롤시 아래와 같은 오류가 발생했습니다. +```swift +2023-09-12 16:28:45.001423+0900 Diary[23292:2537329] [LayoutConstraints] Unable to simultaneously satisfy constraints. + Probably at least one of the constraints in the following list is one you don't want. + Try this: + (1) look at each constraint and try to figure out which you don't expect; + (2) find the code that added the unwanted constraint or constraints and fix it. +( + "", + "", + "" +) + +Will attempt to recover by breaking constraint + + +Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. +The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in may also be helpful. +``` +- 오류 내용을 분석한 결과 Cell이 화면에 보이지 않을 때 발생하는 Constraint(UIView-Encapsulated-Layout-Height)와 제가 부여한 Cell이 Constraints가 충돌하여 나타나는 오류로 보였습니다. + 따라서 해당 오류를 해결하기 위해서 bottomConstraint에 대한 Priority를 999로 낮춰서 constraint가 충돌하는 것을 해결할 수 있었습니다. + + 파악한 오류의 원인만 봐서는 누구나 경험할 수 있는 오류라고 판단됩니다. 그렇게 생각한 이유는 화면에 보이지 않을 때의 셀의 제약조건을 height == 0으로 준다면 어떤 조건이라도 충돌이 발생할 수 있기 때문입니다. + +[문제에 대한 질문: StackOverFlow](https://stackoverflow.com/questions/77043899/using-uitableviewdiffabledatasource-in-uitableview-add-or-deletecell-warning) +오류해결 커밋: (https://github.com/yagom-academy/ios-diary/commit/bc89e580507d90d480db6a61672760fc5ee205ae) + +
+ +### 🔥 DiaryDetailViewController에서 delete시 save 중복 +- `CoreData`의 `content`를 `delete`한 후 이를 `context`에 `save`하는 로직을 구현하였습니다. 이때 하기와 같은 에러가 발생하였습니다. + > [error] error: Mutating a managed object 0xaef4c17744feb12c (0x6000013d75c0) after it has been removed from its context. +- 오류 원인을 `save()`의 공식 문서에서 알 수 있게 되었습니다. + > Always verify that the context has uncommitted changes (using the hasChanges property) before invoking the save: method. Otherwise, Core Data may perform unnecessary work. + > `save`메서드는 호출하기 전 `context`의 변동사항을 체크하는데, 변동사항이 없을 시 `save`를 호출하는 것은 불필요한 작업이 됩니다. + [AppleDeveloper - save()](https://developer.apple.com/documentation/coredata/nsmanagedobjectcontext/1506866-save) + + 이를 기반으로 디버깅을 한 결과 `delete` 시 `save`가 연달아 `두 번` 호출되는 것을 확인할 수 있었습니다. 두번째 화면인 `DiaryDetailViewController`에서 `delete`와 `save`를 한 후 첫번째 화면으로 바로 넘기는데, 첫번째 화면이 띄워지는 과정에서 데이터를 `fetch`하고 `save`를 호출하고 있었습니다. + + 이에 `save` 호출이 중복되지 않게 코드 수정을 하여 에러 발생을 방지하였습니다. + +
+ +### 🔥 Protocol을 활용하여 중복코드 삭제 및 수평적 확장 +- `share`와 `delete` 기능 관련 `AlertController`와 `ActivityViewController` 코드가 각 `ViewController`에서 중복되었습니다. 하여 중복코드를 삭제하면서 `UIViewController`에 `Alert/Activity Controller`의 역할을 확장시킬 수 있도록 하고자 하였습니다. + + 각각 `AlertControllerShowable`, `ActivityViewControllerShowable` 프로토콜을 생성하였습니다. `extension`에 `기본 구현`을 함으로 코드의 중복을 삭제시킬 수 있었습니다. + + 프로토콜을 사용하면 수평적 기능 확장이 가능하게 된다는 장점이 존재합니다. 하지만 무분별하게 확장사용하는 것을 제한할 수 있도록 `where Self`를 사용하여 `UIViewController`에서만 기능 확장 사용이 가능하도록 하였습니다. + +
+ +### 🔥 DiaryDetailViewController에 entity 주입 +- `diary text`를 작성하는 도중 앱이 `background`로 가는 경우 `저장`이 될 수 있도록 구현하고자 하였습니다. 이때 `text`가 있는 경우 새롭게 `create`를 하거나 `update`를 하여 변경된 내용을 저장하고자 하였습니다. + + 저희는 `entity`의 유무로 `create`와 `update`의 기준을 나누었기 때문에, 앱 사용 도중 최초 저장을 하게 되면 `create` 로직을 타고 새로운 `content`를 생성하였습니다. 하지만 `background`에 있던 앱을 다시 `foreground`로 가져와 수정을 완료하여 저장하고자 할 때 `entity`가 없기 때문에 다시 `create`로직을 타는 문제가 생겼습니다. + + 이를 해결하고자 기존의 `DiaryCoreDataManager`의 `createDiaryData` 메서드가 `entity`를 반환하도록 수정하여 `create` 시 `DiaryDetailViewController`에 주입해주었습니다. 이로서 `text`가 있는 경우 중간에 앱이 `background`로 가게되면 바로 `entity`를 `create`하여 새로운 `entity`를 `DiaryDetailViewController`에 주입하였습니다. 이렇게 하여 추가 수정을 완료하여 저장하게 되면 `entity`가 있다고 판단하여 `update`로직을 탈 수 있도록 하였습니다.
@@ -141,4 +220,9 @@ - [🍎 Apple Developer - UICollectionViewDiffableDataSource](https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasource) - [🍎 Apple Developer - Date](https://developer.apple.com/documentation/foundation/date) - [🍎 Apple Developer - DateFormatter](https://developer.apple.com/documentation/foundation/dateformatter) +- [🍎 Apple Developer - Core Data](https://developer.apple.com/documentation/coredata) +- [🍎 Apple Developer - Making Apps with Core Data](https://developer.apple.com/videos/play/wwdc2019/230 +- [🍎 Apple Developer - UITextViewDelegate](https://developer.apple.com/documentation/uikit/uitextviewdelegate) +- [🍎 Apple Developer - UISwipeActionsConfiguration](https://developer.apple.com/documentation/uikit/uiswipeactionsconfiguration) - [📒 Blog - NSDate, DateFormatter](https://velog.io/@dev_jane/NSDate-DateFormatter-사용하여-사용자의-기기에-맞는-날짜-설정하기) +- [📒 Blog - Core Data](https://zeddios.tistory.com/987) From b3a7146b0a6e756cce34602927cf629e40d834fb Mon Sep 17 00:00:00 2001 From: Serena Date: Sun, 17 Sep 2023 16:34:31 +0900 Subject: [PATCH 34/34] =?UTF-8?q?chore:=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Diary/Manager/CoreDataManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Diary/Manager/CoreDataManager.swift b/Diary/Manager/CoreDataManager.swift index 1e3003c99..3da6df394 100644 --- a/Diary/Manager/CoreDataManager.swift +++ b/Diary/Manager/CoreDataManager.swift @@ -82,9 +82,9 @@ final class CoreDataManager: CoreDataManagerType { try context.save() } catch { let nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") } } } - }