From 33cd723105698a2902f933d317bfd7e688a8d6a4 Mon Sep 17 00:00:00 2001 From: hemg2 Date: Fri, 1 Sep 2023 11:41:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20CoreDataManager=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .swiftlint.yml | 1 - Diary+CoreDataClass.swift | 15 ++++++ Diary+CoreDataProperties.swift | 28 +++++++++++ Diary.xcodeproj/project.pbxproj | 20 ++++++++ Diary/App/AppDelegate.swift | 46 ------------------- Diary/App/SceneDelegate.swift | 2 +- .../Controller/DiaryListViewController.swift | 24 ++++++++-- Diary/DataManager/CoreDataManager.swift | 38 +++++++++++++++ .../Diary.xcdatamodel/contents | 9 +++- Diary/View/DiaryListTableViewCell.swift | 12 ++--- 10 files changed, 132 insertions(+), 63 deletions(-) create mode 100644 Diary+CoreDataClass.swift create mode 100644 Diary+CoreDataProperties.swift create mode 100644 Diary/DataManager/CoreDataManager.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 1340cf7cf..18ab66e0b 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,6 +1,5 @@ disabled_rules: - trailing_whitespace -- line_length excluded: - Pods diff --git a/Diary+CoreDataClass.swift b/Diary+CoreDataClass.swift new file mode 100644 index 000000000..4164fcfae --- /dev/null +++ b/Diary+CoreDataClass.swift @@ -0,0 +1,15 @@ +// +// Diary+CoreDataClass.swift +// Diary +// +// Created by 1 on 2023/09/01. +// +// + +import Foundation +import CoreData + +@objc(Diary) +public class Diary: NSManagedObject { + +} diff --git a/Diary+CoreDataProperties.swift b/Diary+CoreDataProperties.swift new file mode 100644 index 000000000..a20279692 --- /dev/null +++ b/Diary+CoreDataProperties.swift @@ -0,0 +1,28 @@ +// +// Diary+CoreDataProperties.swift +// Diary +// +// Created by 1 on 2023/09/01. +// +// + +import Foundation +import CoreData + + +extension Diary { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Diary") + } + + @NSManaged public var title: String? + @NSManaged public var body: String? + @NSManaged public var createdAt: Date? + @NSManaged public var id: UUID? + +} + +extension Diary : Identifiable { + +} diff --git a/Diary.xcodeproj/project.pbxproj b/Diary.xcodeproj/project.pbxproj index 04bba2ca2..1c8506d14 100644 --- a/Diary.xcodeproj/project.pbxproj +++ b/Diary.xcodeproj/project.pbxproj @@ -9,6 +9,9 @@ /* Begin PBXBuildFile section */ 459D493A878338290A3E0AEF /* Pods_Diary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDF8EB908CAD9D062C72898B /* Pods_Diary.framework */; }; 63BB62822A9F109400524DCB /* DecodingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62812A9F109400524DCB /* DecodingManager.swift */; }; + 63BB62B22AA181BE00524DCB /* Diary+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */; }; + 63BB62B32AA181BE00524DCB /* Diary+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */; }; + 63BB62B52AA182AA00524DCB /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63BB62B42AA182AA00524DCB /* CoreDataManager.swift */; }; 63E527352A9D7EBF0000FBA6 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 63E527342A9D7EBF0000FBA6 /* .swiftlint.yml */; }; 63E527372A9D87660000FBA6 /* DiaryListTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E527362A9D87660000FBA6 /* DiaryListTableViewCell.swift */; }; 63E527392A9D97160000FBA6 /* CreateDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63E527382A9D97160000FBA6 /* CreateDiaryViewController.swift */; }; @@ -25,6 +28,9 @@ /* Begin PBXFileReference section */ 63BB62812A9F109400524DCB /* DecodingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodingManager.swift; sourceTree = ""; }; + 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Diary+CoreDataClass.swift"; sourceTree = SOURCE_ROOT; }; + 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Diary+CoreDataProperties.swift"; sourceTree = SOURCE_ROOT; }; + 63BB62B42AA182AA00524DCB /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; 63E527342A9D7EBF0000FBA6 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = ""; }; 63E527362A9D87660000FBA6 /* DiaryListTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryListTableViewCell.swift; sourceTree = ""; }; 63E527382A9D97160000FBA6 /* CreateDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDiaryViewController.swift; sourceTree = ""; }; @@ -73,6 +79,14 @@ name = Frameworks; sourceTree = ""; }; + 63BB62B62AA185E700524DCB /* DataManager */ = { + isa = PBXGroup; + children = ( + 63BB62B42AA182AA00524DCB /* CoreDataManager.swift */, + ); + path = DataManager; + sourceTree = ""; + }; 63E5273C2A9ECD5A0000FBA6 /* App */ = { isa = PBXGroup; children = ( @@ -85,6 +99,8 @@ 63E5273D2A9ECD660000FBA6 /* Model */ = { isa = PBXGroup; children = ( + 63BB62B02AA181BE00524DCB /* Diary+CoreDataClass.swift */, + 63BB62B12AA181BE00524DCB /* Diary+CoreDataProperties.swift */, BA1A55EA2A9D84AF0012C89D /* DiaryEntity.swift */, 63BB62812A9F109400524DCB /* DecodingManager.swift */, ); @@ -147,6 +163,7 @@ C739AE23284DF28600741E8F /* Diary */ = { isa = PBXGroup; children = ( + 63BB62B62AA185E700524DCB /* DataManager */, 63E5273E2A9ECD800000FBA6 /* Extension */, 63E5273D2A9ECD660000FBA6 /* Model */, BABBDAE62A9F13AE00D8D50B /* Error */, @@ -283,9 +300,12 @@ BA1A55ED2A9D90810012C89D /* DateFormatter+.swift in Sources */, 63E527372A9D87660000FBA6 /* DiaryListTableViewCell.swift in Sources */, C739AE2F284DF28600741E8F /* Diary.xcdatamodeld in Sources */, + 63BB62B52AA182AA00524DCB /* CoreDataManager.swift in Sources */, 63E527392A9D97160000FBA6 /* CreateDiaryViewController.swift in Sources */, BABBDAE52A9F13A200D8D50B /* DecodingError.swift in Sources */, + 63BB62B32AA181BE00524DCB /* Diary+CoreDataProperties.swift in Sources */, BA1A55EB2A9D84AF0012C89D /* DiaryEntity.swift in Sources */, + 63BB62B22AA181BE00524DCB /* Diary+CoreDataClass.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Diary/App/AppDelegate.swift b/Diary/App/AppDelegate.swift index ca75bb74e..1961da3c5 100644 --- a/Diary/App/AppDelegate.swift +++ b/Diary/App/AppDelegate.swift @@ -30,51 +30,5 @@ 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 485f9f29a..608a4b0d5 100644 --- a/Diary/App/SceneDelegate.swift +++ b/Diary/App/SceneDelegate.swift @@ -49,7 +49,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // 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() +// (UIApplication.shared.delegate as? AppDelegate)?.saveContext() } diff --git a/Diary/Controller/DiaryListViewController.swift b/Diary/Controller/DiaryListViewController.swift index 27c26b66a..6f6b8c530 100644 --- a/Diary/Controller/DiaryListViewController.swift +++ b/Diary/Controller/DiaryListViewController.swift @@ -15,11 +15,14 @@ final class DiaryListViewController: UIViewController { }() private var diaryEntities = [DiaryEntity]() private let dateFormatter = DateFormatter() + private let container = CoreDataManager.shard.persistentContainer + private var diaryList = [Diary]() override func viewDidLoad() { super.viewDidLoad() setupData() + readCoreData() configureUI() setupTableView() } @@ -63,13 +66,21 @@ final class DiaryListViewController: UIViewController { } catch { print(DecodingError.unknown.message) } - + } + + private func readCoreData() { + do { + let diaryList = try container.viewContext.fetch(Diary.fetchRequest()) + tableView.reloadData() + } catch { + // TODO : AlertController Error + } } } extension DiaryListViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - diaryEntities.count + diaryList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -77,10 +88,13 @@ extension DiaryListViewController: UITableViewDataSource, UITableViewDelegate { for: indexPath) as? DiaryListTableViewCell else { return UITableViewCell() } - let diaryEntity = diaryEntities[indexPath.row] - let date = dateFormatter.formatToString(from: diaryEntity.createdAt, with: "YYYY년 MM월 dd일") + let diaryEntity = diaryList[indexPath.row] + guard let title = diaryEntity.title, + let createdAt = diaryEntity.createdAt, + let body = diaryEntity.body else { return UITableViewCell() } + let date = dateFormatter.formatToString(from: createdAt, with: "YYYY년 MM월 dd일") - cell.setModel(title: diaryEntity.title, date: date, body: diaryEntity.body) + cell.setModel(title: title, date: date, body: body) return cell } diff --git a/Diary/DataManager/CoreDataManager.swift b/Diary/DataManager/CoreDataManager.swift new file mode 100644 index 000000000..b493a0476 --- /dev/null +++ b/Diary/DataManager/CoreDataManager.swift @@ -0,0 +1,38 @@ +// +// CoreDataManager.swift +// Diary +// +// Created by Max, Hemg on 2023/09/01. +// + +import Foundation +import CoreData + +class CoreDataManager { + static let shard = CoreDataManager() + private init() {} + + // MARK: - Core Data stack + lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "Diary") + container.loadPersistentStores(completionHandler: { (storeDescription, error) in + if let error = error as NSError? { + 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 { + let nserror = error as NSError + fatalError("Unresolved error \(nserror), \(nserror.userInfo)") + } + } + } +} diff --git a/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents index 50d2514e8..b15a20237 100644 --- a/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents +++ b/Diary/Diary.xcdatamodeld/Diary.xcdatamodel/contents @@ -1,4 +1,9 @@ - - + + + + + + + \ No newline at end of file diff --git a/Diary/View/DiaryListTableViewCell.swift b/Diary/View/DiaryListTableViewCell.swift index c2cf422f0..e13b5150a 100644 --- a/Diary/View/DiaryListTableViewCell.swift +++ b/Diary/View/DiaryListTableViewCell.swift @@ -57,16 +57,12 @@ final class DiaryListTableViewCell: UITableViewCell { NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5), titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40) - ]) - - NSLayoutConstraint.activate([ + titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40), + dateLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), dateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20), - dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5) - ]) - - NSLayoutConstraint.activate([ + dateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5), + bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), bodyLabel.leadingAnchor.constraint(equalTo: dateLabel.trailingAnchor, constant: 4), bodyLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40),