Skip to content

Commit

Permalink
[feat] 코어데이터 로딩 오류 시 나타나는 에러 뷰 컨트롤러에 디버깅용 문구 추가 #163
Browse files Browse the repository at this point in the history
코어데이터 오류 시 디버깅용 문구를 저장 관련 작업 실패 시에만 추가하고,
앱 실행 시 발생할 수 있는 초기 오류에는 추가하지 않아서 추가함
  • Loading branch information
skkimeo committed Apr 25, 2022
1 parent 855e424 commit 13b2060
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 17 deletions.
7 changes: 5 additions & 2 deletions Happiggy-bank/Happiggy-bank/CoreData/PersistenceStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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)
}
Expand Down
8 changes: 5 additions & 3 deletions Happiggy-bank/Happiggy-bank/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
18 changes: 18 additions & 0 deletions Happiggy-bank/Happiggy-bank/Utils/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
101 changes: 89 additions & 12 deletions Happiggy-bank/Happiggy-bank/ViewController/ErrorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}


Expand All @@ -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:))
))
}
}

0 comments on commit 13b2060

Please sign in to comment.