Skip to content

야곰 아카데미 iOS 일기장 프로젝트 저장소입니다

Notifications You must be signed in to change notification settings

Groot-94/ios-diary

 
 

Repository files navigation

📔 일기장 "Diary"

프로젝트 기간 : 2022.08.16 화 ~ 2022.09.04 일
리뷰어 : Wody


🪧 목차


📜 프로젝트 소개

📔 나만의 일기장을 만들어봅시다! Core location을 사용하여 사용자의 해당 위치를 파악하고, open weather api를 사용하여 실시간 날씨를 받아옵니다. 입력받은 사용자의 일기와 날씨정보를 Core data 방식으로 앱 내부에 저장하는 일기장 어플입니다.


👥 팀원

재재(ZZBAE) 그루트(Groot) (절대권력자)
Github Github

💾 개발환경 및 라이브러리

swift xcode

💡 핵심경험

  • Date Formatter의 지역 및 길이별 표현의 활용
  • Text View의 활용
  • 코어데이터 모델 생성
  • 코어데이터 모델 및 DB 마이그레이션
  • 테이블뷰에서 스와이프를 통한 삭제기능 구현
  • Text View Delegate의 활용
  • Open API의 활용
  • Core Location의 활용


🕰 타임라인

Step 1 첫째 주

날짜 내용
8/16(화) 명세에 있는 공식문서, WWDC, 영상 등 공부
8/17(수) ListView 구현 및 dateFormatter 적용
8/18(목) DetailView 구현 및 RegisterView, 키보드 구현
8/19(금) Step1 PR 및 리드미작성

Step 2 둘째 주

날짜 내용
8/22(월) Step1 리팩토링
8/23(화) 개인공부
8/24(수) 개인공부 및 Step1 리팩토링, 머지
8/25(목) Core Data CRUD 구현, DetailView 자동저장 구현 및 RegisterView 자동저장 구현
8/26(금) Step2 PR 및 리드미작성

Step 3 셋째 주

날짜 내용
8/29(월) Step2 리팩토링
8/30(화) Step2 리팩토링 및 머지
8/31(수) Step3 해당 개인 공부
9/1(목) 날씨 API 받아서 날씨 icon 불러오기
9/2(금) 사용자 지역별 날씨 icon 불러오기 수정 및 Step3 PR
9/4(일) Step3 리팩토링 및 리드미작성


📱 구현 화면

일기장 List 화면 일기장 Detail 화면
List -> Detail 화면 이동 키보드 설정 구현
일기장 생성화면에서 화면이동 시 자동저장 일기장 생성화면에서 백그라운드 전환 시 자동저장
일기장에서 화면이동 시 자동저장 일기장 화면에서 백그라운드 전환 시 자동저장
리스트 화면에서 스와이프를 통한 공유 및 삭제 일기장 화면에서 경고문을 통한 공유 및 삭제
일기장 List view에서
날씨 아이콘을 추가한 화면
일기장 Detail에서
해당 날짜를 title로 가진 화면



🧑‍💻 코드 설명

파일구조

├── CoreDataManager.swift
├── DataModel
│   ├── DiaryModel.swift
│   └── WeatherModel.swift
├── Diary
│   ├── Diary.xcdatamodeld
│   │   ├── Diary.xcdatamodel
│   │   │   └── contents
│   │   └── DiaryWithWeather.xcdatamodel
│   │       └── contents
│   ├── Info.plist
│   ├── Resources
│   │   ├── AppDelegate.swift
│   │   ├── Assets.xcassets
│   │   ├── Base.lproj
│   │   │   └── LaunchScreen.storyboard
│   │   └── SceneDelegate.swift
│   ├── Scene
│   │   ├── DataTask
│   │   │   └── DataTaskViewController.swift
│   │   ├── DiaryDetail
│   │   │   ├── Controller
│   │   │   │   └── DiaryDetailViewController.swift
│   │   │   └── View
│   │   │       └── DiaryDetailView.swift
│   │   ├── DiaryList
│   │   │   ├── Controller
│   │   │   │   └── DiaryListViewController.swift
│   │   │   ├── Model
│   │   │   │   ├── DiaryData.swift
│   │   │   │   ├── DiaryDataManager.swift
│   │   │   │   └── WeatherDataManager.swift
│   │   │   └── View
│   │   │       └── DiaryTableViewCell.swift
│   │   └── DiaryRegister
│   │       ├── Controller
│   │       │   └── DiaryRegisterViewController.swift
│   │       └── View
│   │           └── DiaryRegisterView.swift
│   ├── extension
│   │   └── Double+extension.swift
│   └── protocol
│       └── DiaryDataManagerProtocol.swift
├── Diary+CoreDataClass.swift
├── Diary+CoreDataProperties.swift
├── DiaryTests
│   └── DiaryTests.swift
└── README.md



📁 파일 요약 정리

STEP 1

Scene

DiaryList

DummyData

일기장 리스트를 테스트 하기위한 Data 구조체

  • Sample Json Data를 Decode해서 배열로 반환하는 타입

DiaryTableViewCell

일기장 List를 구현하기 위한 TableViewCell 타입

DiaryListViewController

TableView를 구현하고 Scene의 전환을 위한 Controller 역할

DiaryDetail

DiaryDetailViewController

DiaryListViewController에서 데이터를 전달받아 DiaryDetailView에 전달하는 Controller 역할 DataSendable 채택하여 데이터를 전달(Delegation 전달방식 사용)

DiaryDetailView

일기장의 내용을 편집할 수 있는 뷰

DiaryRegister

DiaryRegisterViewController

새로운 일기장을 생성할 수 있는 뷰 (이번 step에서는 뷰의 layout만 구성)

protocol

DataSendable

Controller간 데이터 전달을 위한 Protocol

extension

Double+extension

convertData()라는 지역과 언어에 따라 해당 언어를 바꿔주는 DateFormatter 함수

DiaryTests

DiaryTests

DummyData의 Json 데이터의 디코딩이 정상적으로 되는지 확인하는 테스트

STEP 2

Scene

CoreDataManager

CoreData를 활용하여 사용자가 적는 일기장 내용을 CRUD (Creat, Read, Update, Delete) 해주는 기능을 관리하는 파일

DiaryRegister

DiaryRegisterViewController

새롭게 적은 일기의 내용을 DiaryListView에 전달하여 추가하는 Controller 역할

DiaryRegisterView

일기의 내용을 새로 적을 수 있는 뷰

DiaryDataManagerProtocol

decoding한 DiaryModel을 타입으로 갖는 diaryItems로 가지고 있는 프로토콜

DiaryData

사용자가 일기 내용을 새로 적은 데이터를 담는 구조체

DiaryDataManager

DiaryData를 인스턴스화하여 provider이란 프로퍼티로 가지고 있는 구조체

STEP 3

Scene

DiaryList

WeatherDataManager

openAPI Get Reqeuest를 사용해 실시간 날씨정보와 Icon 이미지를 받아오기 위한 Data Manager

DataModel

WeatherModel

openAPI 사이트에서 받아올 날씨와 아이콘 WeatherData를 배열로 가지고 있는 WeatherModel




⛹🏻‍♀️ STEP 1 트러블 슈팅

TextView에 긴 Text 설정 시 자동 스크롤 때문에 제목이 잘리는 문제가 있었습니다.

  • 문제점

    • TextView에 text를 설정했을 때 자동으로 스크롤이 되지만, text의 길이가 화면을 넘지 못해 스크롤이 생기지는 않아 제목이 잘리는 문제가 있었습니다.
  • 해결 과정

    • detailTextView를 초기화해주는 클로저에서 contentOffset을 변경해줬지만, 해결하지 못했습니다.
    • 초기화 당시엔 문제가 없지만, Text를 설정해주면서 스크롤이 내려가는 문제가 발생함을 알 수 있었습니다.
  • 해결방법

    • text 설정 후 TextView의 Offset을 초기화 해주는 방법으로 문제를 해결하였습니다.

detailTextView.contentOffset = CGPoint(x: 0, y: 0)
문제화면 해결화면



⛹🏻‍♀️ STEP 2 트러블 슈팅

앱이 백그라운드로 진입하는 경우 일기가 자동저장되게끔 구현을 해주는 방식 고민

  • 어떤 방식으로 백그라운드 진입을 확인할 것인가에 대한 고민
      1. applicationDidEnterBackground(_:) 메서드로 앱이 백그라운드로 갔을 때, 밑의 사진과 같이 didEnterBackgroundNotification와 함께 사용하는 방식이 있었습니다.
      1. 또다른 방식으로는 sceneDelegate 내의 sceneDidEnterBackground 메서드를 사용할 수 있었습니다.
    • 저희는 sceneDelegate에서 navigationController와 rootViewController를 구성했기 때문에 sceneDelegate에의 메서드에서 처리하는게 맞다고 판단했습니다.
  • sceneDidEnterBackground를 사용해서 백그라운드 자동저장 기능을 구현 시 모든 화면에서 저장 메서드를 호출하는 문제가 있었습니다.
    • sceneDelegate의 sceneDidEnterBackground를 사용하는 방법으로 자동저장 기능을 구현했지만, 모든 화면에서 백그라운드 이동 시 일기장 등록 ViewController에 있는 자동저장 메서드가 호출되는 문제가 있었습니다.
  • 현재 window의 NavigationViewContollertopViewContoller을 확인하는 방법으로 저장이 필요한 ViewContoller인지 확인해서 호출하는 방법을 사용했습니다.
    func sceneDidEnterBackground(_ scene: UIScene) {
            guard let navigationViewController = window?.rootViewController as? UINavigationController
            else { return }
    
            let topViewContoller = navigationViewController.topViewController
    
            switch topViewContoller {
            case let viewController as DiaryRegisterViewController:
                viewController.saveDiaryData()
            case let viewController as DiaryDetailViewController:
                viewController.saveDiaryData()
            default:
                break
            }
        }



⌨️ 커밋 규칙

  • feat : 기능 추가 (새로운 기능)
  • refactor : 리팩토링 (네이밍 수정 등)
  • style : 스타일 (코드 형식, 세미콜론 추가: 비즈니스 로직에 변경 없음)
  • docs : 문서 변경 (문서 추가, 수정, 삭제)
  • test : 테스트 (테스트 코드 추가, 수정, 삭제: 비즈니스 로직에 변경 없음)
  • chore : 기타 변경사항 (빌드 스크립트 수정 등)

🔗 참고 링크

[STEP 1]

Adaptivity and Layout
Positioning content relative to the safe area
Positioning content within layout margins
Making apps adaptive part 1
Making apps adaptive part 2
DateFormatter
UITextView
tableView(_:trailingSwipeActionsConfigurationForRowAt:)
UITableViewController VS UIViewController + UITableView
hugging priority, compression priority

[STEP 2]

Core Data
Setting Up a Core Data Stack Manually
UITableViewDelegate
tableView(_:trailingSwipeActionsConfigurationForRowAt:)
UISwipeActionsConfiguration

[STEP 3]

Using Lightweight Migration
Core Data Migration

About

야곰 아카데미 iOS 일기장 프로젝트 저장소입니다

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 99.4%
  • Ruby 0.6%