Skip to content

하루는 더 이상 24시간이 아니다 Remote 레포입니다.

Notifications You must be signed in to change notification settings

Seungwoo-Seo/A-day-is-no-longer-24-hours

Repository files navigation


하루는 더 이상 24시간이 아니다

하루를 n일로 나눠서 n배 효율적인 하루를 계획할 수 있는 서비스

📱 서비스

  • 최소 버전 : iOS 15.0
  • 개발 인원 : 1인
  • 개발 기간 : 2023년 9월 28일 ~ 2023년 10월 28일 (1개월)
  • 버전 : 1.1.1
  • 앱 스토어

🚀 서비스 기능

  • 취침/기상 시간 설정 기능 제공
  • 생활시간 기반 하루를 최적화된 일수로 자동 분할 기능 제공
  • 달력/타임라인 제공
  • Todo 추가/삭제 및 추가 가능 여부 검사 기능 제공

🛠 사용 기술

  • Swift
  • UIKit
  • MVVM, Singleton, Delegate Pattern
  • Realm, SnapKit, FSCalendar, HGCircularSlider, IQKeyboardManager, Tabman
  • CodeBase UI, AutoLayout, Base, Observable, ViewIdentifiable, CompositionalLayout, DiffableDataSource,
Firebase Crashlytics

💻 기술 스택

  • 데이터 바인딩을 위한 Observable 구현
  • ER 다이어그램기반 DB 테이블 설계 및 구현
  • EmbeddedObject를 활용해 Todo, DetailTodo를 1:1로 구성하고 Todo 삭제 시 DetailTodo도 함께 삭제될 수 있도록 구현
  • 생활시간 기반 분 변환, 약수를 활용해 자동 분할 로직 구현
  • HGCircularSlider 기반 수면 시간 측정 UI 구현
  • DiffableDataSource + CompositionalLayout 을 통한 Expandable Timeline 구현
  • Firebase Crashlytics 을 통한 앱 크래시 모니터링 설정

🚧 기술적 도전

데이터 바인딩을 위한 Observable 구현

  • 도전 상황
    뷰 컨트롤러와 뷰 모델 사이의 의존성을 느슨하게 하기 위해서 데이터 바인딩이 필요했고 클로저를 이용한 Observable을 도입

  • 도전 결과

import Foundation

final class CustomObservable<T> {
    private var listener: ((T) -> ())?

    var value: T {
        didSet {
            listener?(value)
        }
    }

    init(_ value: T) {
        self.value = value
    }

    func bind(
        subscribeNow: Bool = true,
        _ closure: @escaping ((T) -> ())
    ) {
        if subscribeNow {
            closure(value)
        }
        listener = closure
    }

}

🚨 트러블 슈팅

textField를 통해 DiffableDataSource item을 업데이트할 때마다 snapshot이 변경되는 이슈

  • 문제 상황
    아래 사진처럼 자세한 할 일을 추가할 때마다 각 셀에서 사용할 item을 뷰모델에서 배열로 가지고 있고 뷰컨에서는 아래 코드와 같이 item 배열이 변할 때마다 snapshot을 업데이트. 그런데 textField에 입력을 해서 text가 변경될 때마다 snapshot이 변경되어버리는 이슈가 발생


override func viewDidLoad() {
        super.viewDidLoad()

        viewModel.detailTodoList.bind { [weak self] (detailTodoList) in
            guard let self else {return}

            var snapshot = NSDiffableDataSourceSnapshot<TodoContentWritingTableViewSection, DetailTodo>()
            snapshot.appendSections(TodoContentWritingTableViewSection.allCases)
            snapshot.appendItems(detailTodoList, toSection: .detail)
            self.dataSource.apply(snapshot)
        }
}
  • 문제 원인
    textField의 text값을 item의 프로퍼티로 가지고 있는데, item이 구조체이기 때문에 text 값을 변경하면 해당 item 또한 변경된 것이기 때문에 snapshot이 업데이트 된 것

  • 해결 방법
    사용할 item을 구조체가 아닌 클래스로 변경

About

하루는 더 이상 24시간이 아니다 Remote 레포입니다.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published