From 35a6cee8920b551afdd31233624c8533712d2f3f Mon Sep 17 00:00:00 2001 From: sun Date: Mon, 25 Apr 2022 14:56:46 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20=EC=BD=94=EC=96=B4=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EB=A1=9C=EB=94=A9=20=EC=98=A4=EB=A5=98=20=EC=8B=9C?= =?UTF-8?q?=20=EB=82=98=ED=83=80=EB=82=98=EB=8A=94=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=B7=B0=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=97=90=20?= =?UTF-8?q?=EB=94=94=EB=B2=84=EA=B9=85=EC=9A=A9=20=EB=AC=B8=EA=B5=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20#163?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코어데이터 오류 시 디버깅용 문구를 저장 관련 작업 실패 시에만 추가하고, 앱 실행 시 발생할 수 있는 초기 오류에는 추가하지 않아서 추가함 --- .../CoreData/PersistenceStore.swift | 7 +- .../Happiggy-bank/SceneDelegate.swift | 8 +- .../Happiggy-bank/Utils/Constants.swift | 18 ++++ .../ViewController/ErrorViewController.swift | 101 +++++++++++++++--- 4 files changed, 117 insertions(+), 17 deletions(-) diff --git a/Happiggy-bank/Happiggy-bank/CoreData/PersistenceStore.swift b/Happiggy-bank/Happiggy-bank/CoreData/PersistenceStore.swift index de5b9da8..43695d9a 100644 --- a/Happiggy-bank/Happiggy-bank/CoreData/PersistenceStore.swift +++ b/Happiggy-bank/Happiggy-bank/CoreData/PersistenceStore.swift @@ -20,7 +20,7 @@ class PersistenceStore { PersistenceStore(name: StringLiteral.sharedPersistenceStoreName) }() - static private(set) var fatalErrorNeeded = false + static private(set) var fatalErrorDescription: String? /// persistence container 의 viewContext 에 접근하기 위한 syntactic sugar private(set) lazy var context: NSManagedObjectContext = { @@ -43,7 +43,10 @@ class PersistenceStore { self.persistentContainer = NSPersistentContainer(name: name).then { $0.loadPersistentStores { _, error in if let error = error as NSError? { - PersistenceStore.fatalErrorNeeded = true + PersistenceStore.fatalErrorDescription = """ + \(error.localizedDescription) + \(error.userInfo) + """ print(error.localizedDescription) print(error.userInfo) } diff --git a/Happiggy-bank/Happiggy-bank/SceneDelegate.swift b/Happiggy-bank/Happiggy-bank/SceneDelegate.swift index 617d1b43..5e976eff 100644 --- a/Happiggy-bank/Happiggy-bank/SceneDelegate.swift +++ b/Happiggy-bank/Happiggy-bank/SceneDelegate.swift @@ -19,12 +19,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let scene = (scene as? UIWindowScene) else { return } - guard PersistenceStore.fatalErrorNeeded == false + guard let errorMessage = PersistenceStore.fatalErrorDescription else { - scene.windows.first?.rootViewController = ErrorViewController() + /// 정상적인 경우 + PersistenceStore.shared.windowScene = scene return } - PersistenceStore.shared.windowScene = scene + /// 코어데이터 에러 발생 + scene.windows.first?.rootViewController = ErrorViewController(errorMessage: errorMessage) } func sceneDidDisconnect(_ scene: UIScene) { diff --git a/Happiggy-bank/Happiggy-bank/Utils/Constants.swift b/Happiggy-bank/Happiggy-bank/Utils/Constants.swift index 160a4033..eb384edb 100644 --- a/Happiggy-bank/Happiggy-bank/Utils/Constants.swift +++ b/Happiggy-bank/Happiggy-bank/Utils/Constants.swift @@ -1174,6 +1174,24 @@ let mainStoryboardName = "Main" extension ErrorViewController { + /// 상수 + enum Metric { + + /// 상하좌우 패딩 (24, -24, 24, -24) + static let paddings = ( + top: edgeInset, + bottom: -edgeInset, + leading: edgeInset, + trailing: -edgeInset + ) + + /// 뷰 간 간격: 16 + static let spacing: CGFloat = 24 + + /// 패딩: 24 + private static let edgeInset: CGFloat = 24 + } + /// 문자열 enum StringLiteral { diff --git a/Happiggy-bank/Happiggy-bank/ViewController/ErrorViewController.swift b/Happiggy-bank/Happiggy-bank/ViewController/ErrorViewController.swift index 03a4dc3b..af504d03 100644 --- a/Happiggy-bank/Happiggy-bank/ViewController/ErrorViewController.swift +++ b/Happiggy-bank/Happiggy-bank/ViewController/ErrorViewController.swift @@ -10,13 +10,37 @@ import UIKit /// 코어데이터 로딩 오류 발생 시 나타나는 뷰 컨트롤러 final class ErrorViewController: UIViewController { + // MARK: - Properties + + /// 에러메시지 + private var errorMessage: String! + + /// 유저에게 에러와 메일 주소를 안내하는 라벨 + private var informationLabel: UILabel! + + /// 디버깅용 문구를 나타내는 텍스트뷰 + private var errorMessageTextView: UITextView! + + + // MARK: - Inits + + init(errorMessage: String) { + super.init(nibName: nil, bundle: nil) + self.errorMessage = errorMessage + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + // MARK: - Life Cycle override func viewDidLoad() { super.viewDidLoad() - self.view.backgroundColor = .systemBackground - self.configureInformationLabel() + self.configureView() + self.configureViewHierarchy() } @@ -30,26 +54,79 @@ final class ErrorViewController: UIViewController { // MARK: - Functions + /// 뷰 초기설정 + private func configureView() { + self.view.backgroundColor = .systemBackground + self.view.addGestureRecognizer(UITapGestureRecognizer( + target: self, + action: #selector(userDidTap(sender:)) + )) + self.configureInformationLabel() + self.configureErrorMessageTextView() + } + /// 에러 안내 라벨 생성 private func configureInformationLabel() { - let informationLabel = UILabel().then { + self.informationLabel = UILabel().then { $0.textColor = .customWarningLabel $0.numberOfLines = .zero $0.textAlignment = .center $0.text = StringLiteral.informationLabelText $0.translatesAutoresizingMaskIntoConstraints = false } - - self.view.addSubview(informationLabel) + } + + /// 텍스트뷰 초기 설정 + private func configureErrorMessageTextView() { + self.errorMessageTextView = UITextView().then { + $0.textColor = .label + $0.font = UIFont.systemFont(ofSize: UIFont.labelFontSize) + $0.isEditable = false + $0.showsHorizontalScrollIndicator = false + $0.text = self.errorMessage + $0.translatesAutoresizingMaskIntoConstraints = false + } + } + + /// 뷰 체계 구성 + private func configureViewHierarchy() { + self.view.addSubview(self.informationLabel) + self.view.addSubview(self.errorMessageTextView) + self.configureInformationLabelConstraints() + self.configureErrorMessageTextViewConstraints() + } + + /// 정보 라벨 오토레이아웃 설정 + private func configureInformationLabelConstraints() { NSLayoutConstraint.activate([ - informationLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), - informationLabel.centerYAnchor.constraint(equalTo: self.view.centerYAnchor) + self.informationLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), + self.informationLabel.topAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.topAnchor, + constant: Metric.paddings.top + ) + ]) + } + + /// 에러 메시지 텍스트뷰 오토레이아웃 설정 + private func configureErrorMessageTextViewConstraints() { + NSLayoutConstraint.activate([ + self.errorMessageTextView.topAnchor.constraint( + equalTo: self.informationLabel.bottomAnchor, + constant: Metric.spacing + ), + self.errorMessageTextView.bottomAnchor.constraint( + equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, + constant: Metric.paddings.bottom + ), + self.errorMessageTextView.leadingAnchor.constraint( + equalTo: self.view.leadingAnchor, + constant: Metric.paddings.leading + ), + self.errorMessageTextView.trailingAnchor.constraint( + equalTo: self.view.trailingAnchor, + constant: Metric.paddings.trailing + ) ]) - - self.view.addGestureRecognizer(UITapGestureRecognizer( - target: self, - action: #selector(userDidTap(sender:)) - )) } }