-
Notifications
You must be signed in to change notification settings - Fork 75
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
일기장 [STEP 2] Zion, Serena #136
base: ic_9_serena
Are you sure you want to change the base?
Conversation
private var isUpdate: Bool { | ||
diaryEntity != nil | ||
} |
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.
isUpdate
가 무엇을 의미하나요?
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.
entity
의 유무를 기준으로 update
를 할지, create
를 할지 분기처리하였습니다!
하여 isUpdate
가 true
인 경우 create
가 아닌 update
를 타게 됩니다.
private let date: String | ||
weak var delegate: DiaryDetailViewControllerDelegate? | ||
|
||
init(date: String, diaryEntity: DiaryEntity? = nil) { | ||
self.date = date | ||
self.diaryEntity = diaryEntity | ||
|
||
super.init(nibName: nil, bundle: nil) | ||
} |
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.
계속 코드를 보는데 굳이 date까지 주입을 받아야 되나라는 생각이 드네요..
의존성을 주입 받는 기준이 무엇인가요?
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.
해당 객체는 ViewController이기 때문에 View를 보여주는 것이외의 다른 것들을 주입받거나 가지고 있을 필요가 없다고 생각했습니다.
주입받는 것이아니라 내부에서 가지고 사용한다면 그만큼 재사용성이 떨어지는 것이라고 생각합니다.
따라서 View를 보여주기 위한 date를 주입받아서 사용했습니다 스티븐
// MARK: - Button Action | ||
extension DiaryDetailViewController { | ||
@objc | ||
func didTappedMoreButton() { |
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 붙일 수 있을 것 같아요 ㅎㅎ
protocol ActivityViewControllerShowable where Self: UIViewController { | ||
func showActivityViewController(items: [Any]) | ||
} | ||
|
||
extension ActivityViewControllerShowable { | ||
func showActivityViewController(items: [Any]) { | ||
let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) | ||
|
||
present(activityViewController, 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.
ActivityViewControllerShowable
과 AlertControllerShowable
은 protocol을 사용하지 않고 그냥 UIViewController 익스텐션으로만 구현해줘도 되지 않았을까요?
protocol로 빼신 이유가 있으신가요?
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.
해당 ViewController가 위의 Controller들을 Show 할 수 있음을 명시하기위해 사용했습니다.
협업을 하게 된다면 다른 사람들이 만든 Extension을 전부 확인하고 사용할 수 없다고 생각합니다.
위와 같은 이유로 Extension의 사용을 지양했습니다. :)
final class DiaryCoreDataManager: CoreDataManager { | ||
func createDiaryData(title: String, body: String, date: Double) -> DiaryEntity { | ||
let entity = DiaryEntity(context: context) | ||
|
||
entity.title = title | ||
entity.body = body | ||
entity.date = date | ||
return entity | ||
} | ||
} |
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.
return 값이 불필요하다 생각되어 CoreDataManager 및 CoreDataManager와 ViewController가 상호작용하는 방식 전면을 Refactoring했습니다. create와 관련된 코드도 범용적으로 변경했습니다 스티븐!
Diary/Manager/AppManager.swift
Outdated
} | ||
|
||
private func convertDiaryData(text: String) -> (String, String)? { | ||
let separatedText = text.split(separator: "\n", maxSplits: 1) |
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.
여기는 String 익스탠션을 사용해도 좋을 것 같아요 ㅎㅎ
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.
convertDiaryData는 String의 역할이 아니라고 생각합니다 스티븐
그 이유는 해당 로직은 특정 String을 받아서 과제에서 제시하고 있는 Separator인 "\n"을 받아서 Title, Body로 나누어서 이를 Tuple형식으로 변환하여 반환하고 있습니다. 이는 범용적으로 활용될 수 있는 부분은 아니라고 생각합니다.
따라서 extension으로 사용하지 않고 별도의 메서드로 분리하여 처리했습니다! 조언 감사합니다!
Step2
@stevenkim18
안녕하세요! 스티븐
Zion, Serena 팀 입니다!
다이어리 프로젝트 Step2 리뷰 잘 부탁드립니다😊
고민한 부분
🔥 ViewController에서의 DiaryCoreDataManager에 대한 의존성
ViewController
(이하 VC)는VC
를 띄우는 데 있어서 필요한 데이터가 아닌 다른 것들을 의존하게 된다면 재사용성이 많이 떨어질 수 밖에 없다고 생각합니다. 따라서 이를 위해 상위 타입인AppManager
를 만들게 되었습니다.하지만 과제를 추가적으로 진행해나가면서
VC
에 진입할 때 마다fetch
한 데이터를 갱신하고,Delete
기능들 등이 추가되면서DiaryCoreDataManager
를 직접적으로VC
에서 주입했다면 재사용성은 떨어져도 코드의 가독성 및 이후의 유지 보수 관련해서는 더 쉽게 이해할 수 있는 코드가 되지않을까? 라고 생각했습니다. 그렇게 생각한 이유는DiaryCoreDataManager
를 주입받지 않았을 때 발생하는AppManager
와의 많은 소통때문이라고 생각합니다.물론 결과물만 올바르게 나온다면 두가지 방법 모두 좋다고 생각합니다. 또한 두가지의 경우를 모두 지키는 코드를 작성하는 것은 매우 어렵다고 생각합니다. (하나를 잃으면 하나를 얻는 관계라고 생각하기 때문에) 코드를 작성하시면서 이와 같은 요소들(재사용성 및 가독성)에 대한 우선순위나 VC에 대한 의존성을 관리할 때 조금더 생각하거나 고려하시는 부분들이 있는지 여쭤보고싶습니다.
🔥 TableView delete 한 후 Scroll할 때의 Constraint 충돌
TableView
에서는DiffableDataSource
을 활용하여Cell
을 관리하고 있습니다.Cell
을Swipe
했을 때 존재하는Delete
기능을 사용하여 Cell을 삭제하고 스크롤시 아래와 같은 오류가 발생했습니다.오류 내용을 분석한 결과
Cell
이 화면에 보이지 않을 때 발생하는Constraint(UIView-Encapsulated-Layout-Height)
와 제가 부여한Cell
이Constraints
가 충돌하여 나타나는 오류로 보였습니다.따라서 해당 오류를 해결하기 위해서
bottomConstraint
에 대한Priority
를 999로 낮춰서constraint
가 충돌하는 것을 해결할 수 있었습니다.파악한 오류의 원인만 봐서는 누구나 경험할 수 있는 오류라고 판단됩니다. 그렇게 생각한 이유는 화면에 보이지 않을 때의 셀의 제약조건을
height == 0
으로 준다면 어떤 조건이라도 충돌이 발생할 수 있기 때문입니다. 해당 오류는DiffableDataSource
를 사용하여Delete
동작을 사용했기 때문에 경험한 것인지 아니면 해당 오류가 발생하는 다른 이유가 있는 것인지 여쭤보고 싶습니다.문제에 대한 질문: StackOverFlow
오류해결 커밋: (bc89e58)
🔥 CoreDataManager에 CRUD 구현
CoreData
를 관리를 담당할CoreDataManager
객체를 만들어CoreData
와 관련된 로직처리를 하고자 하였습니다.CoreData
의CRUD
역할 중create
는 범용적인 코드로 하기 한계가 있다고 생각했습니다.Data
별로entity
가 가지는value
는 변할 수 있기 때문입니다. 하여DiaryCoreDataManager
를 별도로 만들어Diary
라는 특정Data
를 위한 객체를 만들어create
역할을 맡기고자하였습니다.이때 한가지 의문이 들었습니다.
create
를DiaryCoreDataManager
에게 모두 넘겨야할지, 아니면 둘 다create
역할을 알고 있어야할지 고민이 되었습니다.처음엔
create
의 역할을CoreDataManager
에서도 갖고 있어야한다고 생각하였습니다.CoreDataManager
에서 구현된create
를 기반으로DiaryCoreDataManager
에서 구체적인data
에 맞춘create
메서드를 구현해야한다 생각했기 때문입니다.하지만 이런 경우
CoreDataManager
에 불필요하게 중복 코드가 생기는 것인가에 대한 고민이 들었습니다. 하여CoreDataManager
에서create
메서드를 삭제하고create
는DiaryCoreDataManager
에서만 구체적으로 구현하였습니다.🔥 DiaryDetailViewController에서 delete시 save 중복
CoreData
의content
를delete
한 후 이를context
에save
하는 로직을 구현하였습니다. 이때 하기와 같은 에러가 발생하였습니다.오류 원인을
save()
의 공식 문서에서 알 수 있게 되었습니다.이를 기반으로 디버깅을 한 결과
delete
시save
가 연달아두 번
호출되는 것을 확인할 수 있었습니다. 두번째 화면인DiaryDetailViewController
에서delete
와save
를 한 후 첫번째 화면으로 바로 넘기는데, 첫번째 화면이 띄워지는 과정에서 데이터를fetch
하고save
를 호출하고 있었습니다.이에
save
호출이 중복되지 않게 코드 수정을 하여 에러 발생을 방지하였습니다.🔥 Protocol을 활용하여 중복코드 삭제 및 수평적 확장
share
와delete
기능 관련AlertController
와ActivityViewController
코드가 각ViewController
에서 중복되었습니다. 하여 중복코드를 삭제하면서UIViewController
에Alert/Activity Controller
의 역할을 확장시킬 수 있도록 하고자 하였습니다.각각
AlertControllerShowable
,ActivityViewControllerShowable
프로토콜을 생성하였습니다.extension
에기본 구현
을 함으로 코드의 중복을 삭제시킬 수 있었습니다.프로토콜을 사용하면 수평적 기능 확장이 가능하게 된다는 장점이 존재합니다. 하지만 무분별하게 확장사용하는 것을 제한할 수 있도록
where Self
를 사용하여UIViewController
에서만 기능 확장 사용이 가능하도록 하였습니다.🔥 DiaryDetailViewController에 entity 주입
diary text
를 작성하는 도중 앱이background
로 가는 경우저장
이 될 수 있도록 구현하고자 하였습니다. 이때text
가 있는 경우 새롭게create
를 하거나update
를 하여 변경된 내용을 저장하고자 하였습니다.저희는
entity
의 유무로create
와update
의 기준을 나누었기 때문에, 앱 사용 도중 최초 저장을 하게 되면create
로직을 타고 새로운content
를 생성하였습니다. 하지만background
에 있던 앱을 다시foreground
로 가져와 수정을 완료하여 저장하고자 할 때entity
가 없기 때문에 다시create
로직을 타는 문제가 생겼습니다.이를 해결하고자 기존의
DiaryCoreDataManager
의createDiaryData
메서드가entity
를 반환하도록 수정하여create
시DiaryDetailViewController
에 주입해주었습니다. 이로서text
가 있는 경우 중간에 앱이background
로 가게되면 바로entity
를create
하여 새로운entity
를DiaryDetailViewController
에 주입하였습니다. 이렇게 하여 추가 수정을 완료하여 저장하게 되면entity
가 있다고 판단하여update
로직을 탈 수 있도록 하였습니다.