# PR 안녕하세요, 하비(@havilog)🙇🏻‍♂️🙇🏻! [Ayaan🦖](https://github.com/oneStar92), [zhilly🔥](https://github.com/zhilly11)입니다! 이번 스텝도 잘 부탁드립니다!!😁 Coredata 어렵네요...😭 # 📍고민했던 부분 ## ObjectID 사용 - CoreData의 Object에서 UUID를 id로 사용하여 관리할지 제공되는 ObjectID를 이용할지를 고민했습니다. - UUID를 사용하면 특정 object를 얻으려면 fetch작업을 따로 정의해서 사용해야 하는 단점이 있었습니다. - objectID를 사용하면 context의 메서드를 이용해서 update, delete를 손쉽게 사용할 수 있기 때문에 objectID를 사용했습니다. ## CoreDataStack 구현 - CRUD를 구현하기 위해서 CoreData의 Container를 이용해야했습니다. - AppDelegate에 구현을 해두면 사용할 때마다 AppDelegate에서 가져오고 언래핑하고 할당해주는 번거로움이 있었습니다. - 따라서 CRUD의 역할을 해주는 CoreDataStack 이라는 싱글톤 객체로 만들어서 사용했습니다. ## 모델 - CoreData로 사용하는 모델 하나로 구현을 해야할까, 아니면 앱에서 실질적으로 사용하는 모델 타입 하나를 추가로 만들어 두개의 모델로 구현을 해야할 까 고민했습니다. - 한 개로 하면 CoreData 모델이 비즈니스 로직을 담당할 수는 있겠지만, CoreData 모델의 역할이 많아진다고 판단했습니다. - 그렇다고 ViewController에서 비즈니스 로직을 담당하는 것도 아키텍처 관점에서 어긋난다고 생각했습니다. - 따라서 실질적으로 사용하는 모델 타입을 만들어 비즈니스 로직을 처리하게 하여 이를 해결하였습니다. <br> # 📍해결하지 못한 부분 ## **TemploryID(미해결)** - NSFetchedResultsController를 이용하여 CoreData가 수정될때마다 자동으로 Diary List가 갱신되도록 구현했습니다. - NSFetchedResultsController에서 받아오는 Snapshot은 TemploryID값이 포함되어 전달되는 문제가 발생했습니다. - (TemploryID가 생성되는 이유는 아직 저장되지 않은 경우 개체 ID는 개체가 저장될 때 변경되는 임시 값입니다. [참고](https://developer.apple.com/documentation/coredata/nsmanagedobject/1506848-objectid)) - 처음 생성된 임시 objectID `<x-coredata:///Task/tE1C5A230-A419-42D5-AF78-3327A09D13BD2>` - 앱을 종료후 실행시킨 뒤 objectID `<x-coredata://D6703834-ECB4-487B-84F8-330A215E16B7/Task/p13>` - 해당 문제를 해결하는 방법을 찾지 못해서 NSFetchedResultsController를 사용하지 않고 Diary List를 갱신하도록 구현했습니다. - havi는 혹시 이 현상을 해결하는 방법을 알고 계신가요??? <br> # 📍조언을 얻고 싶은 부분 - DiaryCell을 모두 지운 후 +버튼을 클릭하게 되면 아래와 같은 AutoLayout 오류가 발생합니다. - `UIStackView:0x136f23080.bottom == UITableViewCellContentView:0x136f23450.bottom - 8`로 발생되는 문제로는 파악했으나 어떻게 해결해야 되는지 감이 잡히지 않습니다... 도와주세요 havi🙇🏻‍♂️ ![](https://i.imgur.com/6htmjuB.gif) ```bash 2022-12-28 21:46:34.502911+0900 Diary[92290:4407591] [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. ( "<NSLayoutConstraint:0x6000000dc5f0 V:|-(8)-[UIStackView:0x136f23080] (active, names: '|':UITableViewCellContentView:0x136f23450 )>", "<NSLayoutConstraint:0x6000000dc640 UIStackView:0x136f23080.bottom == UITableViewCellContentView:0x136f23450.bottom - 8 (active)>", "<NSLayoutConstraint:0x6000000a3e80 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x136f23450.height == 0 (active)>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x6000000dc640 UIStackView:0x136f23080.bottom == UITableViewCellContentView:0x136f23450.bottom - 8 (active)> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful. ``` 추가적으로 조언을 얻고 싶은 부분은 코멘트로 남겨놓았습니다!! --- # PR 안녕하세요, 하비(@havilog)🙇🏻‍♂️🙇🏻! [Ayaan🦖](https://github.com/oneStar92), [zhilly🔥](https://github.com/zhilly11)입니다! 중간 중간 뜻밖에 오류들을 만나서 조금 해멨습니다 🥲 많이 알려주시면 열심히 배우겠습니다 ✏️ 3주간 리뷰 잘 부탁드립니다! # 📍고민했던 부분 ## MainStoryboard없이 Code로 구현 - 요구사항에 코드로만 UI를 작성하라는 문구가 있어서 시도해보았습니다. 1. Main.storyboard 삭제 2. info.plist에서 storyboard관련 삭제 3. SceneDelegate에서 ViewController로 이동할 수 있도록 RootViewController 설정 - 이와 같이 진행하고 실행시에 Main스토리보드 관련하여 에러가 뜨는 것을 확인했습니다 1. 프로젝트 설정에서 Info탭에서 추가로 StoryBoard관련해서 삭제 2. Build Settings에서 main storyboard관련 삭제 ![](https://i.imgur.com/6IpdAis.png) - 위의 추가 과정을 통해 Main 스토리보드 없이 프로젝트를 진행할 수 있었습니다! ## NavigationBar 구분선 - MainStoryboard가 없이 코드로만 UI를 구성해 봤습니다. `NavigationController`및 `rootViewController`를 `SceneDelegate`에서 인스턴스화 해주어서 첫 화면이 보여지게 구현해 봤습니다. 하지만 iOS 15부터 NavigationBar의 디자인이 수정되어 구분선이 보이지 않는 현상이 발생했습니다. - `UINavigationBarAppearance`를 인스턴스화 한 후 `configureWithOpaqueBackground()`메서드로 현재 테마에 적합한 불투명한 bar appearance object로 구성한 뒤 `NavigationController.navigationBar`에 `standardAppearance`및 `scrollEdgeAppearance`에 할당해 줌으로 이전에 발생한 문제를 해결했습니다. ## UITableDataSource - `TableView`의 `DataSource`로 `UITableViewDiffableDataSource`를 사용했습니다. `UITableViewDiffableDataSource`의 경우 `ItemIdentifier`가 `Hashable`해야했으며 `ItemIdentifier`에 해당하는 `Diary` Type은 `Hashable`하지 못하는 문제가 발생했습니다. - `Diary` Type이 인스턴스화 될 때 프로퍼티로 `UUID`를 할당해 줌으로 해당 문제를 해결했습니다. - `Diary` Type이 `UUID`를 프로퍼티로 가지고 있는 것이 좋은 방향성인지 많은 고민을 했으나 추후 `CoreData`에서 검색등의 작업을 할때도 이러한 프로퍼티가 있으면 좋을 것 같다고 판단했습니다. ## Locale - 지역 및 언어에 맞는 작성일자를 표현해주려고 했습니다. 하지만 `Locale.current`의 값이 지역을 변경하고 언어를 변경해도 `eu_KR`과 같이 언어 부분이 `eu`로 표현되는 문제가 발생했습니다. - `Locale.preferredLanguages.first`를 사용하여 설정된 언어 중 첫번째 언어에 해당하는 값으로 작성일자를 표현되게 해주어 문제를 해결했습니다. ## DiaryView 재사용 고민 - Diary 수정화면과 작성화면을 구현하는 과정에서 ViewController를 2개로 구현해야할까 라는 고민을 했었습니다. - 고민해본 결과 2개의 ViewController보다는 1개에서 처리를 해서 재사용을 하자라는 방식으로 진행했습니다. # 📍조언을 얻고 싶은 부분 조언을 얻고 싶은 부분은 코멘트로 남겨놓았습니다!! ![](https://i.imgur.com/KDKMb8l.png) ![](https://i.imgur.com/vW4CMqj.png) navigationbar 구분선 문제 iOS15 부터 스타일이 바뀜 standardApperence scroll~Apperence 는 같은 값이어야 한다? 둘 중에 뭐가 좋을까 static let identifier: String = String(describing: self) static func getIdentifier() -> String { return String(describing: self) } ## ------ PR ------