Bible Typing App

kmjmarine·2023년 4월 27일
0

앱 개발 노트

목록 보기
2/2

App Architecture

  • MVP design pattern
  • Xcode / Version 13.2.1 (13C100)
  • without storyboard
  • swift 5 100%

Identity

GitHub

Open API

ETC

  • simulator - iPhone 12 pro max

2022.7.5

2022.7.9

  • Define TypingList
  • Define old, new Bible Data

2022.7.12

  • collectionView에 대한 고찰

2022.7.13

  • 닫기 버튼 탭 시 정상 작동 안 함 수정 필요
@objc func didTabCancelButton() {
    self.present(TypingListViewController(), animated: true, completion: nil) //오류
    dismiss(animated: true, completion: nil) //오류
    self.navigationController?.pushViewController(TypingListViewController(), animated: <#T##Bool#>) //오류
}
  • NavigationController push했기 때문에 pop처리 (NavigationController stack 구조)
//TypingListViewController
navigationController?.pushViewController(typingDetailViewController, animated: true)

//TypingDetailViewController
self.navigationController?.popViewController(animated: true)
  • UserDefaults 구현 -> UUID()로 변경

2022.7.19

  • Operator function '==' requires that 'BibleType' conform to 'StringProtocol'
  • enum의 타입과 비교 변수의 타입을 String으로 일치 시킴
enum BibleType: String {
    case old
    case new
}
self.bookkind == BibleType.old.rawValue

2022.7.21

  • String+ extension 추가
  • "kor-" + ge 문자열 조합 목적

2022.7.22

  • TypingListViewController / StackView 구현 시 CustomTableCell 사라짐 현상 처리 필요

2022.7.25

  • 날짜 형식 변환 코드
func formattedDateString(dateString: String) -> String {
    //String -> Date -> String
    //2022-07-25 -> 7/25
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"

    if let date = formatter.date(from: dateString) {
        formmatter.dateFormat = "M/d"
        return formmater.string(from: date)
    } else {
        return ""
    }
}

2022.7.26

  • Define NavigationController
  • Define Puzzle struct

2022.7.29

  • System colors(ios)
  • NavigationController Background, Custom Title Color설정
  • Define UIColor+
  • Install Toast

2022.8.1

  • Setting Timer move to PuzzleDetailViewContoller

2022.8.2

  • Define ProgressBar
progressView.layer.cornerRadius = 6
progressView.clipsToBounds = true
progressView.transform = progressView.transform.scaledBy(x: 1, y: 6) // 양옆 모서리가 뾰족하게 표현되어
주석 처리 후 해당 snp에서 높이를 지정함
  • 정상 표현 됨 ($0.height.equalTo(10.0))
  • 성경구절 공백 기준 자르고 배열로 변환
let arrQuote = quote.components(separatedBy: " ")
  • Define UILabel+
    • Label의 줄 간격 조절 기능
    • https://ios-development.tistory.com/739
    • 코드 리펙토링 필요 (줄간격 조절, 폰트 백그라운드 컬러 설정 기능 합침 / PuzzleDetailViewController.swift)

2022.8.3

  • 정답 낱말 setting의 ButtonStackView 생성
  • 정답 낱말 선택 시 정답 유무 alert처리
view.makeToast("짝짝짝! 정답이에요.")
   
view.makeToast("앗! 세번째에 들어갈 낱말과 다른 낱말이에요.")
  • 정답 선택 시 예문 구절 backGroundColor 재 설정 필요
  • NSMutableAttributedString
    • 새로운 스타일 적용 시 기존 스타일 사라짐 현상 발생
    • 일단 기존 스타일을 재 적용하는 것으로 처리

2022.8.6

2022.8.7

  • 정답 시 새로운 입력 view로 이동
  • 맞춘 낱말 buttonTitleColor 변경

2022.8.8

  • 새로고침 rightBarButtonItem 추가
func setupNavigationBar() {
    navigationItem.rightBarButtonItem = rigthBarButtonItem
}
  • 장,절 입력 삭제
let startIdx: String.Index = quoteText.index(quoteText.startIndex, offsetBy: 4) //장, 절 삭제

2022.8.9

  • TestFlight 이슈 해결
  • 다크모드 입력 테스트 시 font 색상 안보임 수정 (systemBackground -> label)
attribtuedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.label, range: NSRange(location: chrSourceText, length: 1))

2022.8.10

  • TestFlight 이슈 해결
  • 키보드 완료 버튼 탭 시 저장 버튼과 같은 효과 처리
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    guard text == "\n" else { return true }
        
    presenter.didTabConfirmButton(sourceText: sourceQuoteLabel.text, writeText: writeQuoteTextView.text)
        
    textView.resignFirstResponder()
        
    return true
}
@objc func didTabConfirmButton() {
    presenter.didTabConfirmButton(sourceText: sourceQuoteLabel.text, writeText: writeQuoteTextView.text)
    self.view.endEditing(true)
}
  • SE version Autolayout 수정
  • NavigationController back button 탭 시 타이머 재 설정 처리
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
        
    timeLeft = 5
    progressTime = 0.0
}
  • 구절 문자열이 길 경우 키보드 숨김 처리 (빈 곳 탭 시) - SE version등 해상도 낮은 기기에서 writeText 가림 이슈
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

2022.8.13

  • UIButton '통독전' 처리 (입력한 내역 Record 값이 1개라도 있으면 다음 입력할 장 절 표시)
  • UIButton -> UILabel처리 (탭이 안되는 이유 확인 필요)
  • 통독 완료 처리

2022.8.14

  • 장:절 동적으로 제거 (기존은 4자리로 고정되어 있었음)
func getMakeQuote(_ chpater: Int, _ verse: Int) -> Int {
    let chapterLength: Int = String(chpater).count
    let verseLength: Int = String(verse).count
        
    return chapterLength + verseLength + 2 //"1:10 (장+절) + 공백+콜론 2 더함"
}
  • 장을 다 저장했을 경우 통독 완료 버튼 처리

2022.8.15

  • jsonBible.json 파일 생성 -> 로컬 json 파일 생성 목적(각 절의 총 절 수 데이터 가져오기 위함)
  • json parsing 에러 발생 시 json 파일에 주석을 삭제 확인
  • 해당 장의 마지막 절 값 구해옴 (출애굽기 1장은 22절이 마지막)
if let indexJson = bibleList.Bibles.firstIndex(where: { $0.bookName == bookname && $0.chapter == chapter }) {
    doneChapter = bibleList.Bibles[indexJson].chapter
    doneVerse = bibleList.Bibles[indexJson].verse
}
  • '통독완' 처리

2022.8.16

  • '통독완'인 경우 pushToTypingViewController 안되도록 처리 필요
  • json data 오류 시 alert 처리
func showCloseAlertController() {
    let alertController = UIAlertController(title: "데이터 읽기에 실패 했습니다.\n잠시 후에 다시 시도해 주세요.", message: nil, preferredStyle: .alert)
      
    let closeAction = UIAlertAction(title: "닫기", style: .destructive) {[weak self] _ in
        self?.dismiss(animated: true)
    }
        
    [closeAction].forEach { action in
       alertController.addAction(action)
    }
        
    present(alertController, animated: true)
}
  • Xcode - General - Device Orientation - Portrait 체크로 세로 고정 설정이 안되어 AppDelegate에 코드 삽입
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

2022.8.17

  • define IntroViewController
  • introViewContoller에 Lotti 이미지 노출
    • intro2.json
  • add IntroViewController - rootViewController 로 지정
  • NavigationController, TabbarController 두 개의 back 버튼이 생김
self.tabBarController?.navigationController?.isNavigationBarHidden = true //tabBarController의 back버튼 영역 hidden 처리

2022.8.18

  • TypingListCollectionViewCell 에서 UIButton tab 안되는 이슈
    • UIButton -> UILabel 로 수정
    • 향후 CustomCell에서 UIButton 탭 시 TypingDetailViewController 로 push 하는 부분으로도 가능해야 함
@objc func didTabConfirmButton() {
    ///TypingDetailViewController로 이동 구현 필요
}

2022.8.22

  • add UISwitch
  • rightBarButtonItem 2개 넣기
  • setRightBarButtonItems 와 rightBarButtonItems 차이

2022.8.27

  • IntroViewController version 정보 가져오기 (General - Identity - Version), Build 추가?
guard let info = Bundle.main.infoDictionary,
          let currentVersion = info["CFBundleShortVersionString"] as? String else { return }
versionLabel.text = "v" + currentVersion
private extension UIDevice {
    static func vibrate() {
        AudioServicesPlaySystemSound(1005)
    }
}
  • 정답 입력 시 정답 이미지 노출
    • Lottie 이미지 추가
    • 2초 timeInterval 후 viewWillAppear 실행

2022.8.28

  • 통독 완료 화면 및 TypingListviewController로 push 처리

2022.8.30

  • 북마크 TabbarController 추가
  • BookmarkListViewController 생성

2022.8.31

  • 북마크 해제 추가
  • delBookmark (UserDefaults) 해당 데이터 찾아서 remove
func delBookmark(_ newValue: Bookmark) {
    var currentBookmakrs: [Bookmark] = getBookmark()
        
    if let index = currentBookmakrs.firstIndex(where: { $0.bookname == newValue.bookname && $0.chapter == newValue.chapter && $0.verse == newValue.verse
    }) {
        currentBookmakrs.remove(at: index)
            
        UserDefaults.standard.setValue(
            try? PropertyListEncoder().encode(currentBookmakrs),
            forKey: Key.bookmarks.value
        )
    }
}

2022.9.4

  • 다국어 추가 (영어)

    • Localizable.strings 작성

    • PROJECT에 Korean 추가

    • 언어설정 가져오기

    • 폰의 언어 설정을 가져와 다른 데이터 노출

let quoteList: [Puzzle] = languageCode  == "ko" ? Puzzle.puzzleKOList :  Puzzle.puzzleENList
  • 다국어 버튼 사이즈 조정
button.setPreferredSymbolConfiguration(.init(pointSize: 30, weight: .regular, scale: .default), forImageIn: .normal)
- String Extension 추가 (앱 종료, 재시작없이 actionSheet에 따라 설정된 언어로 변경)
var localized: String { //computed property
    var language = UserDefaults.standard.array(forKey: "language")?.first as? String
        if language == nil {
            let str = String(NSLocale.preferredLanguages[0])    // 언어코드-지역코드 (ex. ko-KR, en-US)
            language = String(str.dropLast(3))                  // ko-KR => ko, en-US => en
        }
    
    let path = Bundle.main.path(forResource: language, ofType: "lproj") ?? Bundle.main.path(forResource: "en", ofType: "lproj")
    let bundle = Bundle(path: path!)
    
    return (bundle?.localizedString(forKey: self, value: nil, table: nil))!
}

2022.9.6

  • String+ 수정
if language == "zh" {
    language = "zh-Hans" //zh-Hans.lproj  파일명으로 재할당
}

2022.9.8

  • 다국어 독일어(de) 추가

2022.9.13

  • 북마크 collectionView -> tableView 로 변경
  • 밀어서 삭제 구현
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let action = UIContextualAction(style: .normal, title: nil) { [weak self] (action, view, completion) in
        let bookmarks = self!.bookmark[indexPath.row]
        self!.userDefaultsManager.delBookmark(bookmarks)
        self!.bookmark.remove(at: indexPath.row)
        self!.viewController?.setupDoneView(bookmarks: self!.bookmark)
        
        tableView.deleteRows(at: [indexPath], with: .automatic)
        completion(true)
    }
    
    action.backgroundColor = .red
    action.image = UIImage(systemName: "trash")
    let configuration = UISwipeActionsConfiguration(actions: [action])
    configuration.performsFirstActionWithFullSwipe = false
    return configuration
}
  • 밀어서 삭제에 클립보드 추가 구현
let configuration = UISwipeActionsConfiguration(actions: [deleteAction, copyAction])
  • 코드에 정의한 순서와 반대로 나오는 현상 있음
- 다국어 프랑스어(fr) 추가

2022.9.16

  • TTS기능 구현
    • TTSManager class delegate 연결 (text play 완료 시 스피커 이미지 반전)
//TypingDetailViewController
override func viewDidLoad() {
    super.viewDidLoad()
    
    TTSManager.shared.synthesizer.delegate = self
    
    presenter.viewDidLoad()
}

extension TypingDetailViewController: AVSpeechSynthesizerDelegate {
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        TTSButton.setImage(UIImage(systemName: "speaker.wave.3"), for: .normal)
        TTSManager.shared.stop()
    }
}
  • 성경명 길 경우 폰트 사이즈 줄이기
    • label.adjustsFontSizeToFitWidth = true (is not working)
bookLabel.snp.makeConstraints {
    $0.width.equalTo(90.0) //가로 사이즈를 지정해야 UILabel의 가로 사이즈 넘어갈 경우 label.adjustsFontSizeToFitWidth 작동
}
  • 북마크 language code 추가 필요
    • 해당 언어 코드에 맞는 language로 play
let utterance = AVSpeechUtterance(string: string)
utterance.voice = AVSpeechSynthesisVoice(language: languageCode)

2022.9.18

  • 앱 심사 거부
  • 다국어 alertSheet 위치 미지정 (iPad)
actionSheet의 모달스타일은 UIModalPresentationPopover라고 설명을 해주면서 UIModalPresentationPopover을 사용 할 때는 barButtonItem또는 팝업에 대한 위치를 설정해줘야 된다고 명시
  • iPad 분기처리하여 alertSheet 위치지정
if UIDevice.current.userInterfaceIdiom == .pad { //디바이스 타입이 iPad일때
  if let popoverController = alertController.popoverPresentationController {
      // ActionSheet가 표현되는 위치를 저장해줍니다.
      popoverController.sourceView = self.view
      popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.maxY, width: 0, height: 0)
      popoverController.permittedArrowDirections = []
      self.present(alertController, animated: true, completion: nil)
  }
} else {
  self.present(alertController, animated: true, completion: nil)
}

2022.9.19

  • 북마크 정렬 기능 추가
    • navigationItem.setRightBarButtonItems 대신 아래와 같이 처리 (LargeTitle 시 버튼 위치 우측 상단에 위치함 / 이를 아래로 내림)
      - navigationController?.navigationBar.addSubview(rightBarButtonItem)
    • tableViewCell 에서 정렬이 아니라 userDefaults의 Bookmark 데이터를 정렬 후 TableView.reloadData() 를 실행
func sortBookmark(mode: String) {
    if mode == "time" {
        bookmark.sort { $0.date! > $1.date! }
    } else {
        bookmark.sort { $0.bookname < $1.bookname }
    }
    viewController?.reloadTableView()
}

2022.9.20

  • TypingList 에서 '통독완'인 경우 탭 시 TypingDetail로 이동 -> TypingDetailDone 으로 바로 이동 (pushViewController 두번 하는 버그 해결 )
    • 일단 홀딩

2022.9.21

  • 북마크 삭제 UIContextualAction에 alertContoller 추가 (삭제 한번 더 확인)
  • presenter UIView에서 present method 호출이 불가하여 viewContoller에(indexPath 기준으로 삭제 행위 포함) 작성 후 호출
profile
shared knowledge is long, life is short

0개의 댓글