Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

동기화 메모장 [STEP1] 제인, 호박, 아리 #76

Merged
merged 16 commits into from
Feb 9, 2022

Conversation

leeari95
Copy link
Member

@leeari95 leeari95 commented Feb 8, 2022

안녕하세요. 웨더! @SungPyo

제인 @siwonkim0 호박 @hoBahk 아리 @leeari95 입니다!
이번 동기화 메모장 프로젝트 잘 부탁드립니다 👍 🐵

일단 저희가 고민할 수 있는 부분들은 모두 구현해본 것 같은데요. 🤔
혹시 부족한 점이나 놓친 부분이 있다면 번거롭더라도 한번 더 짚어주시면 감사하겠습니다. 🙇🏻‍♀️

실행화면

초기화면
셀 선택
실시간 반영
자동 스크롤
편집모드 종료

고민했던 점

1. 키보드 가림현상 개선 및 편집모드 종료 구현

  • NotificationCenter를 활용하여 키보드가 화면에 표시될 때 UITextView도 키보드의 높이만큼 contentInset을 조정하도록 구현하였습니다.
  • 편집을 끝낸 후 다른 메모를 눌렀을 때 편집모드를 종료할 수 있도록 구현했습니다. UITapGestureRecognizer를 활용하여 사용자가 텍스트뷰가 아닌 다른 부분을 터치했을 때 endEditing 메소드를 호출하도록 하였습니다.

2. 실시간으로 수정된 메모가 UITableView에 반영되도록 구성

  • 실시간 반영을 위해 UITextViewDelegate를 활용하여 UITextView가 수정될 때 마다 데이터를 수정하고, UITableView도 업데이트하도록 기능을 구현하였습니다.

3. Crash를 방지

  • 존재하지않는 인덱스를 조회했을 때 Crash가 나지 않도록 subscript를 활용하여 Crash가 발생하지 않도록 구현하였습니다.
extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

4. Dynamic Type

  • UILabel, UITextView에 실시간으로 글씨 크기를 조정할 수 있도록 다이나믹 폰트 설정 및 Automatically Adjusts Font 기능을 활성화 해주었습니다.

5. 메모를 터치했을 때 secondary 뷰컨에 상세 메모를 표시하도록 구현

  • MemoListViewController의 UITableViewDelegate 메서드 didSelectRowAt에서 SplitViewController의 present메서드를 통해 눌린 테이블뷰 셀의 indexPath를 활용하였습니다.
  • indexPath로 SplitViewController가 가지고있는 Memo 배열 타입의 데이터 중에서 해당되는 데이터를 골라서 MemoDetailViewController의 text view를 업데이트를 합니다.

6. 인터페이스가 축소되었을때 먼저 보여지는 뷰를 secondary가 아니라 primary로 설정

  • 아이패드에서 스플릿뷰로 다른 앱과 화면을 같이 쓰는 경우 화면이 작아져서 primary와 secondary뷰가 한번에 보이지 않아, primary뷰인 메모목록이 먼저 보여지도록 delegate 메서드를 통해 설정해주었습니다.

궁금했던 것 / 조언이 필요한 점

SplitViewController의 secondary의 배경색이 회색인 문제

  • preferredSplitBehavior를 tile로 대입해줘도 해당 문제가 해결되지 않아서 MemoDetailViewController의 view의 배경색을 .systemBackground로 대입해주어 해결하였는데, 적절한지 모르겠습니다.

데이터를 primary(MemoListViewController)와 secondary(MemoDetailViewController)에 효율적으로 뿌려줄 순 없을까요?

  • 아래 두가지 경우일 때 indexPath를 전달하여 데이터를 관리하고 있습니다.
    • primary의 tableView Cell이 선택되었을 때
      • index를 primaryVC > splitVC > secondaryVC 거쳐서 전달
    • secondary가 업데이트 되었을 때
      • index를 secondaryVC > splitVC > primaryVC 거쳐서 전달
  • splitVC을 거쳐가는 방식 말고 더 좋은 방법은 없을지... 조언이 필요합니다!

Locale

  • 날짜를 포맷팅할 때 선호하는 언어first를 가져와서 languageCode 프로퍼티를 활용하여 locale에 대입해주고 있습니다.
  • 원래는 디바이스의 언어에 맞춰 포맷팅을 해주고 싶어, Locale.current로 대입해주었었으나, 해결할 수가 없었어요.
    • Locale.current를 사용하니 en_KR로 나타나는 것을 확인했는데.. 왜 이렇게 나오는건지.. 조언이 필요합니다!!
// 수정 전
extension TimeInterval {
    var formattedDate: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        dateFormatter.locale = Locale.current
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: Date(timeIntervalSince1970: self))
    }
}

// 수정 후
extension TimeInterval {
    var formattedDate: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        let localeID = Locale.preferredLanguages.first
        let deviceLocale = Locale(identifier: localeID ?? "ko-kr").languageCode
        dateFormatter.locale = Locale(identifier: deviceLocale ?? "ko-kr")
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: Date(timeIntervalSince1970: self))
    }
}

3주간 잘부탁드리겠습니다~ 😁🙏🏻

leeari95 and others added 16 commits February 7, 2022 15:43
- Asset에 sample JSON 파일 추가
- Memo 타입에 오타를 수정
- 기존에 설정되어있는 스토리보드 설정을 모두 제거
- Bundle identifier를 설정
- MemoListViewController, MemoDetailViewController의 navigationItem 설정
- SceneDelegate에서 SplitViewController의 이니셜라이저 수정
- MemoListCell 타입 생성하여 테이블뷰의 셀 등록
- SplitViewController의 프로퍼티에서 MemoListViewController의 이니셜라이저 수정
- NotificationCenter를 활용하여 TextView에 자동스크롤 기능 구현
- MemoListViewController의 tableView Delegate 메서드 추가
- MemoListCell의 configure 메서드 수정
- MemoDetailViewController의 setUpData 메서드 추가
- 뷰에 보여줄 모델 생성 (MemoListInfo, MemoDetailInfo)
- TimeInterval extension 추가
- SplitViewController에서 파싱 및 초기데이터 설정 구현
- MemoListVC에서 MemoDetailVC로 화면전환시 셀의 indexPath를 전달함
- MemoDetailVC의 textView delegate 메서드 textViewDidChange 에서 textView가 수정될때마다 MemoListVC를 업데이트하도록 구현함
- 배열을 안전하게 조회할 수 있도록 Collection extension을 추가하여 기능 구현
- createMemoData 메소드 내부를 개선
- MemoListCell의 dateLabel의 ContentHuggingPriority를 설정
- UIViewController를 extension해서 hideKeyboard 메소드 구현
- splitVC에 hideKeyboard 메소드를 호출하도록 추가
- MemoDetailVC 내부에 createMemoData 메소드 잘못된 부분을 수정
- ViewController를 extension 및 MARK주석으로 분리
- 메서드 순서 개선
- 지역 포맷에 맞게 작성일자를 표현할 수 있도록 DateFormatter의 locale 개선
@SungPyo
Copy link

SungPyo commented Feb 9, 2022

안녕하세요. 웨더! @SungPyo

제인 @siwonkim0 호박 @hoBahk 아리 @leeari95 입니다! 이번 동기화 메모장 프로젝트 잘 부탁드립니다 👍 🐵

일단 저희가 고민할 수 있는 부분들은 모두 구현해본 것 같은데요. 🤔 혹시 부족한 점이나 놓친 부분이 있다면 번거롭더라도 한번 더 짚어주시면 감사하겠습니다. 🙇🏻‍♀️

실행화면

초기화면

셀 선택

실시간 반영

자동 스크롤

편집모드 종료

고민했던 점

1. 키보드 가림현상 개선 및 편집모드 종료 구현

  • NotificationCenter를 활용하여 키보드가 화면에 표시될 때 UITextView도 키보드의 높이만큼 contentInset을 조정하도록 구현하였습니다.
  • 편집을 끝낸 후 다른 메모를 눌렀을 때 편집모드를 종료할 수 있도록 구현했습니다. UITapGestureRecognizer를 활용하여 사용자가 텍스트뷰가 아닌 다른 부분을 터치했을 때 endEditing 메소드를 호출하도록 하였습니다.

2. 실시간으로 수정된 메모가 UITableView에 반영되도록 구성

  • 실시간 반영을 위해 UITextViewDelegate를 활용하여 UITextView가 수정될 때 마다 데이터를 수정하고, UITableView도 업데이트하도록 기능을 구현하였습니다.

3. Crash를 방지

  • 존재하지않는 인덱스를 조회했을 때 Crash가 나지 않도록 subscript를 활용하여 Crash가 발생하지 않도록 구현하였습니다.
extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

4. Dynamic Type

  • UILabel, UITextView에 실시간으로 글씨 크기를 조정할 수 있도록 다이나믹 폰트 설정 및 Automatically Adjusts Font 기능을 활성화 해주었습니다.

5. 메모를 터치했을 때 secondary 뷰컨에 상세 메모를 표시하도록 구현

  • MemoListViewController의 UITableViewDelegate 메서드 didSelectRowAt에서 SplitViewController의 present메서드를 통해 눌린 테이블뷰 셀의 indexPath를 활용하였습니다.
  • indexPath로 SplitViewController가 가지고있는 Memo 배열 타입의 데이터 중에서 해당되는 데이터를 골라서 MemoDetailViewController의 text view를 업데이트를 합니다.

6. 인터페이스가 축소되었을때 먼저 보여지는 뷰를 secondary가 아니라 primary로 설정

  • 아이패드에서 스플릿뷰로 다른 앱과 화면을 같이 쓰는 경우 화면이 작아져서 primary와 secondary뷰가 한번에 보이지 않아, primary뷰인 메모목록이 먼저 보여지도록 delegate 메서드를 통해 설정해주었습니다.

궁금했던 것 / 조언이 필요한 점

SplitViewController의 secondary의 배경색이 회색인 문제

  • preferredSplitBehavior를 tile로 대입해줘도 해당 문제가 해결되지 않아서 MemoDetailViewController의 view의 배경색을 .systemBackground로 대입해주어 해결하였는데, 적절한지 모르겠습니다.

저는 전혀 문제 안된다고 생각합니다.

데이터를 primary(MemoListViewController)와 secondary(MemoDetailViewController)에 효율적으로 뿌려줄 순 없을까요?

  • 아래 두가지 경우일 때 indexPath를 전달하여 데이터를 관리하고 있습니다.

    • primary의 tableView Cell이 선택되었을 때

      • index를 primaryVC > splitVC > secondaryVC 거쳐서 전달
    • secondary가 업데이트 되었을 때

      • index를 secondaryVC > splitVC > primaryVC 거쳐서 전달
  • splitVC을 거쳐가는 방식 말고 더 좋은 방법은 없을지... 조언이 필요합니다!

음.. 요 부분은 화면 전환에 대한 설계를 좀 더 생각해 보면 더 좋은 방법이 나올 수 있다고 생각됩니다. 저런 데이터만 취급하는 클래스를 따로 판다던지..! 물론 현재가 이상하진 않아요. 제가 코드를 보는데 있어서도 크게 불편한건 따로 없었습니다.(또는 제가 스플릿 뷰에 대한 지식이 부족해서 생기는 문제일수도...)

Locale

  • 날짜를 포맷팅할 때 선호하는 언어first를 가져와서 languageCode 프로퍼티를 활용하여 locale에 대입해주고 있습니다.

  • 원래는 디바이스의 언어에 맞춰 포맷팅을 해주고 싶어, Locale.current로 대입해주었었으나, 해결할 수가 없었어요.

    • Locale.current를 사용하니 en_KR로 나타나는 것을 확인했는데.. 왜 이렇게 나오는건지.. 조언이 필요합니다!!

정확히 뭐가 문제다! 라고 말씀드리기는 다른 이유가 있을수도 있으니 살짝 곤란한것 같고. 프로젝트의 실행 언어 설정이 잘못되어 있는 경우에도 문제를 일으킨다고 어디선가 본 것 같은데 그것 때문이 아닐까 살짝 의심해 봅니다.

// 수정 전
extension TimeInterval {
    var formattedDate: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        dateFormatter.locale = Locale.current
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: Date(timeIntervalSince1970: self))
    }
}

// 수정 후
extension TimeInterval {
    var formattedDate: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        let localeID = Locale.preferredLanguages.first
        let deviceLocale = Locale(identifier: localeID ?? "ko-kr").languageCode
        dateFormatter.locale = Locale(identifier: deviceLocale ?? "ko-kr")
        dateFormatter.timeZone = TimeZone.current
        return dateFormatter.string(from: Date(timeIntervalSince1970: self))
    }
}

3주간 잘부탁드리겠습니다~ 😁🙏🏻

전체적으로 보기 불편하지 않고 잘 된것 같아요 :) 다만 한가지만 조언해 보려고 하는데요! 현재 Momo 모델을 제외한 나머지 두개의 모델이 사실 왜 필요한건지 이해하기 힘들었습니다. 새로운 모델을 만드는 다른 이유가 있을까요?

Step1 고생하셨고 Step2에서 봬요!

@SungPyo SungPyo merged commit 6b6deff into yagom-academy:4_leeari95 Feb 9, 2022
@leeari95
Copy link
Member Author

leeari95 commented Feb 10, 2022

새로운 모델을 만드는 다른 이유

  • 뷰에 보여줄 요소들을 별도의 타입으로 만들어두면 좋지 않을까 라는 조언을 듣고 만들어보게 되었는데요. 저번에 디스코드에 와주셨을 때도 좋은 의견인 것 같다고 동의해주셔서 만들어보게 되었습니다! 혹시 저희가 이해를 잘못한 것 일까요?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants