- 프로젝트 기간: 2023년 8월 28일 ~ 9월 15일
- 프로젝트 팀원: Whales🐬, Mary🐿️
- 프로젝트 리뷰어: havi🐠
🍀 소개
💻 실행 화면
🛠️ 사용 기술
👀 다이어그램
🧨 트러블 슈팅
📚 참고 링크
👩👧👧 about TEAM
📙 새 일기 작성 및 저장된 일기 수정이 가능한 일기장 앱입니다. 📗
새 일기 작성 | 저장된 일기 수정 |
---|---|
구현 내용 | 도구 |
---|---|
아키텍쳐 | MVC |
UI | UIKit |
로깅방식 | OS_Log |
지원 언어 | 한국어, English |
🚨 문제점
- Json 샘플 파일에는 다이어리가 생성된 날짜를
timeInterval 형태(ex. 1608651333)
로 가지고 있습니다. 하지만 ViewController에서는 생성 날짜를원하는 포맷(ex. 2020년 12월 23일)
으로 바꿔준 후 UI에 활용하기때문에, 활용할 때마다 DateFormat을 변경하는 것은 비효율적이라고 생각했습니다.
💡 해결방법
- JSON decoding 시 활용하는 객체(DTO)와 실제 모델에서 활용하는 객체(Entity)를 분리해줌으로써 해결하였습니다.
- 다이어리가 생성된 날짜를 timeInterval 형태로 가지는 DTO와 달리 Entity는 원하는 포맷으로 변환한 date를 가지고있습니다.
- 다이어리를 생성하거나, decoding할 때에만 DateFormat을 변경하고, 이후에는 저장된 date를 이용합니다.
🔀 코드 변화
-
수정 전
struct DiaryContent: Codable { var title: String var body: String var timeInterval: Double private enum CodingKeys: String, CodingKey { case title, body case timeInterval = "created_at" } }
-
수정 후
// DTO struct DiaryContentDTO: Decodable { var title: String var body: String var timeInterval: Double private enum CodingKeys: String, CodingKey { case title, body case timeInterval = "created_at" } } // Entity struct DiaryContent { var title: String var body: String var date: String }
Asset
에 넣은 "sample"
데이터를 받아오는 메서드를 구현하는데, 이 작업은 View
나 Controller
의 역할이 아니라고 생각해서 DiaryManager
라는 객체를 Model
로 만들었습니다. DiaryViewController
가 DiaryManager
를 가지고 있고, DiaryManager
가 데이터 fetch
작업을 할 수 있도록 메서드를 구현하였습니다.
수정 전
struct DiaryManager {
func fetchDiaryContents(name: String) -> [DiaryContent]? {
do {
let data: [DiaryContent] = try DecodingManager.decodeJSON(fileName: name)
return data
} catch {
os_log("%{public}@", type: .default, error.localizedDescription)
}
return nil
}
}
final class DiaryViewController: UIViewController {
private let diaryManager = DiaryManager()
private var data: [DiaryContent]?
...
override func viewDidLoad() {
...
fetchData()
}
...
private func fetchData() {
data = diaryManager.fetchDiaryContents(name: "sample")
}
}
🚨 문제점
DiaryViewController
가DiaryManager
를 가지고 있긴 하지만fetchData
메서드에서manager
의 메서드를 호출해 일을 시킴으로써Controller
가 데이터를 받아오는 일을 하게되고, 그로 인해fetchDiaryContents
메서드를 은닉화 할 수 없었습니다.
💡 해결방법
DiaryViewController
에서 필요한diaryContents
를DiaryManager
의 연산프로퍼티로 구현하고, 그 연산에fetchDiaryContents
메서드를 호출해서 문제점들을 해결하였습니다.
수정 후
struct DiaryManager {
var diaryContents: [DiaryContent]? {
return fetchDiaryContents(name: "sample")
}
private func fetchDiaryContents(name: String) -> [DiaryContent]? {
do { ... } catch { ... }
}
}
final class DiaryViewController: UIViewController {
private let diaryManager = DiaryManager()
...
}
extension DiaryViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return diaryManager.diaryContents?.count ?? 0
}
...
}
더 깔끔하고 통일성있는 컨벤션을 위해 SwiftLint를 적용했습니다.
🚨 문제점
- SwiftLint를 프로젝트에 적용했더니 빌드 시 경고가 발생하였습니다.
💡 해결방법
- SwiftLint에서 디폴트로 적용되는 Rule 때문에 발생한 문제였습니다.
.swiftlint
파일을 다음과 같이 수정하여 저희의 컨벤션과 맞춰줌으로써 해결하였습니다.disabled_rules: - trailing_whitespace - trailing_comma
- 🍎Apple Docs: os_log
- 🍎Apple Docs: UIScrollView.KeyboardDismissMode
- 🍎Apple Docs: Adaptivity and Layout
- 🍎Apple Docs: DateFormatter
- 🍎Apple Docs: UITextView
- 🍎Apple Docs: Swipe-trailing
- 🍎Apple Docs: UIActivityViewController
- 🍏WWDC: Making Apps Adaptive, Part 1
- 🍏WWDC: Making Apps Adaptive, Part 2
- 🍏WWDC note: UIKit: Apps for Every Size and Shape
- SwiftLint Rule Directory
- 야곰닷넷: Test Double
- blog: URL 처리 방법
🐬Whales🐬 | https://github.com/WhalesJin | |
---|---|---|
🐿️Mary🐿️ | https://github.com/MaryJo-github |