-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
카테고리 CRUD를 CoreData와 연결하여 구현 #99
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
변경된 줄 수와 파일은 많은데.. 사실 네이밍 변경된 것도 많고 보일러 플레이트 뿐입니다
이 모든게 영현님 덕분이죠 CoreData 길을 뚫어주셔서 감사합니다,,
sheet.detents = [.custom(identifier: .categorySheet) { _ in | ||
categoryViewController.calculateSheetHeight() | ||
}] | ||
sheet.detents = [.medium(), .large()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이제 CategoryViewModel이 카테고리 목록을 직접 Fetch 해오기 때문에 커스텀 높이 시트지를 사용할 수가 없어서
우선은 Medium ~ Large로 높이를 고정적으로 두어 해결했습니다
추후 수정할게요
let container = NSPersistentContainer(name: CoreDataStorage.modelName) | ||
let container = NSPersistentContainer(name: CoreDataStorage.modelName, managedObjectModel: Self.memorialHouseModel) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CoreData: error: Failed to load model named "우리팀모델.xcdatamodeld"
위 문제가 발생해서 다음과 같이 수정해주었습니다.
private func performDatabaseTask<T>( | ||
_ task: @escaping (NSManagedObjectContext) throws -> T | ||
) async -> Result<T, MHDataError> { | ||
let context = coreDataStorage.persistentContainer.viewContext | ||
do { | ||
return try await context.perform { | ||
do { | ||
return .success(try task(context)) | ||
} catch let error as MHDataError { | ||
MHLogger.debug("Core Data 에러: \(error.description)") | ||
throw error | ||
} catch { | ||
MHLogger.debug("알 수 없는 Core Data 에러: \(error.localizedDescription)") | ||
throw error | ||
} | ||
} | ||
} catch let error as MHDataError { | ||
return .failure(error) | ||
} catch { | ||
return .failure(MHDataError.generalFailure) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코어데이터 CRUD 로직이 겹치길래 얘로 묶어줬는데, 다른 분들 코드에 적용해보면 어떨까요 ??
중복되는 코드 길이를 줄일 수 있을 거 같습니당
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋아욤!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
구뜨!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERROR를 처리할 때 Result의 failure와 throw를 나누신 의도가 궁금합니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yuncheol-AHN
내부 디버깅이랑 호출하는 곳에서의 에러 처리를 동시에 해주려고 그랬습니다 !!
crud 메소드에서 발생한 throw를 해당 메소드 catch에서 잡고 디버그 로그로 출력하고 이걸 Result로 반환합니다 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무 고생많으셨습니다... 대대대대대대효준님...
private func performDatabaseTask<T>( | ||
_ task: @escaping (NSManagedObjectContext) throws -> T | ||
) async -> Result<T, MHDataError> { | ||
let context = coreDataStorage.persistentContainer.viewContext | ||
do { | ||
return try await context.perform { | ||
do { | ||
return .success(try task(context)) | ||
} catch let error as MHDataError { | ||
MHLogger.debug("Core Data 에러: \(error.description)") | ||
throw error | ||
} catch { | ||
MHLogger.debug("알 수 없는 Core Data 에러: \(error.localizedDescription)") | ||
throw error | ||
} | ||
} | ||
} catch let error as MHDataError { | ||
return .failure(error) | ||
} catch { | ||
return .failure(MHDataError.generalFailure) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋아욤!!
/// - 주요 특징: | ||
/// - `NSPersistentContainer`를 활용해 Core Data 스택을 구성합니다. | ||
/// - `saveContext` 메서드를 통해 변경된 컨텍스트를 저장합니다. | ||
public class CoreDataStorage: @unchecked Sendable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시
public final class CoreDataStorage: Sendable {
static let modelName: String = "MemorialHouseModel"
nonisolated(unsafe) static let memorialHouseModel: NSManagedObjectModel = {
guard let modelURL = Bundle(for: CoreDataStorage.self).url(
forResource: CoreDataStorage.modelName,
withExtension: "momd"
) else {
fatalError("Error loading model from bundle")
}
return NSManagedObjectModel(contentsOf: modelURL)!
}()
let persistentContainer: NSPersistentContainer
public init() {
let container = NSPersistentContainer(
name: CoreDataStorage.modelName,
managedObjectModel: Self.memorialHouseModel
)
container.loadPersistentStores { _, error in
guard let error else { return }
MHLogger.error("\(#function): PersistentContainer 호출에 실패; \(error.localizedDescription)")
}
self.persistentContainer = container
}
...
}
요렇게 하셔도 에러 뜨시나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lazy 사용하지 않는 방식인 거죵 ?
한 번 해보겠습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
문제없이 잘 돌아가네요, 저도 lazy 방식보다 정현님 말씀대로 하는게 좋은 거 같습니다
수정해서 올릴게요 !!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
참 테스트코드에서 final class MockCoreDataStorage: CoreDataStorage {}
이렇게 사용하고 있어서 final은 제거하겠습니다 !!
// FIXME: MainActor 제거 | ||
@MainActor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅋㅋㅋㅋ Swift6의 쓴맛...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅠㅠ.. 우리의 숙원
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
금요일도 쉬지 않으시는 군요...
대 효 준 🔥 열 정 보 이 🔥
private func performDatabaseTask<T>( | ||
_ task: @escaping (NSManagedObjectContext) throws -> T | ||
) async -> Result<T, MHDataError> { | ||
let context = coreDataStorage.persistentContainer.viewContext | ||
do { | ||
return try await context.perform { | ||
do { | ||
return .success(try task(context)) | ||
} catch let error as MHDataError { | ||
MHLogger.debug("Core Data 에러: \(error.description)") | ||
throw error | ||
} catch { | ||
MHLogger.debug("알 수 없는 Core Data 에러: \(error.localizedDescription)") | ||
throw error | ||
} | ||
} | ||
} catch let error as MHDataError { | ||
return .failure(error) | ||
} catch { | ||
return .failure(MHDataError.generalFailure) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
구뜨!
private func performDatabaseTask<T>( | ||
_ task: @escaping (NSManagedObjectContext) throws -> T | ||
) async -> Result<T, MHDataError> { | ||
let context = coreDataStorage.persistentContainer.viewContext | ||
do { | ||
return try await context.perform { | ||
do { | ||
return .success(try task(context)) | ||
} catch let error as MHDataError { | ||
MHLogger.debug("Core Data 에러: \(error.description)") | ||
throw error | ||
} catch { | ||
MHLogger.debug("알 수 없는 Core Data 에러: \(error.localizedDescription)") | ||
throw error | ||
} | ||
} | ||
} catch let error as MHDataError { | ||
return .failure(error) | ||
} catch { | ||
return .failure(MHDataError.generalFailure) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ERROR를 처리할 때 Result의 failure와 throw를 나누신 의도가 궁금합니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무너무 수고 많으셨습니다 .ᐟ.ᐟ 덕분에 큰 산을 넘은 것 같네요 🥹
let bookCategory = NSManagedObject(entity: entity, insertInto: context) | ||
bookCategory.setValue(category.order, forKey: "order") | ||
bookCategory.setValue(category.name, forKey: "name") | ||
try context.save() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: CoreDataStorage를 보면 실은 saveContext라는 메서드가 있어서.. try를 쓰지 않고도 저장할 수 있긴한데�이것도 괜찮아 보이네용.. saveContext 메서드는 지울까엽??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
옷 그러네요..!
지워도 좋을 거 같아용
private func handleError(with errorMessage: String) { | ||
let alertController = UIAlertController( | ||
title: "에러", | ||
message: errorMessage, | ||
preferredStyle: .alert | ||
) | ||
let okAction = UIAlertAction(title: "확인", style: .default) | ||
alertController.addAction(okAction) | ||
|
||
present(alertController, animated: true) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
캬.. 에러처리까지.. 역시 효준님 .. 그저 "빛" 입니다 ✨
dismiss(animated: true, completion: nil) | ||
} | ||
|
||
func tableView( | ||
_ tableView: UITableView, | ||
heightForRowAt indexPath: IndexPath | ||
) -> CGFloat { | ||
CategoryTableViewCell.height | ||
BookCategoryTableViewCell.height |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3: 혹시 이제 Cell의 갯수에 따른 시트지의 높이를 계산하지 않아도 된다면 위에서 tableView.rowHeight = 00
이렇게 설정해줘도 되지 않을까?? 싶습니당
// FIXME: MainActor 제거 | ||
@MainActor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤯
#️⃣ 연관된 이슈
⏰ 작업 시간
📝 작업 내용
📸 스크린샷
📒 리뷰 노트
performDatabaseTask
메소드로 묶어주었습니다.⚽️ 트러블 슈팅
HomeViewController에서 시트지 버튼을 누르면,
기존에는 HomeViewModel이 카테고리를 들고 있었기 때문에 미리 CategoryViewController의 높이를 알아내고 Present 시킬 수 있었다.
그러나, 이제 CategoryViewModel이 카테고리 목록을 직접 Fetch 해오기 때문에 커스텀 높이 시트지를 사용할 수가 없었다.
우선은 Medium ~ Large로 높이를 고정적으로 두어 해결하였다.