Skip to content

Latest commit

ย 

History

History
303 lines (246 loc) ยท 13.5 KB

README.md

File metadata and controls

303 lines (246 loc) ยท 13.5 KB


๐Ÿงญ 4Most

์ด์ƒ์ด ์ผ์ƒ์ด ๋˜๋Š” ํšŒ๊ณ , 4most

๊ฐœ๋ฐœ๊ธฐ๊ฐ„: 2020.12.27 ~ 2021.01.16


๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป Team4Most - iOS Developer

์ด์œ ์ง„ ์‹ ์œค์•„ ์žฅํ˜œ๋ น
lee-yujinn YoonAh-dev hryeong66
๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž…
๊ธฐ๋ก
๋ชฉํ‘œ
ํšŒ๊ณ 
๋งˆ์ดํŽ˜์ด์ง€ ์„ค์ •
ํ‚ค์›Œ๋“œ ์„ค์ •
๋งˆ์ดํŽ˜์ด์ง€ ํ‚ค์›Œ๋“œ


โš™๏ธ ๊ฐœ๋ฐœํ™˜๊ฒฝ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

swift xcode iOS Moya Alamofire lottie-ios


๐Ÿ–ผ ์„œ๋น„์Šค Workflow

flow

๐Ÿ“ฑ ๊ธฐ๋Šฅ ๋ช…์„ธ์„œ

์ฃผ์š”๊ธฐ๋Šฅ ์ƒ์„ธ๊ธฐ๋Šฅ ์šฐ์„ ์ˆœ์œ„ ๋‹ด๋‹น์ž ๊ตฌํ˜„
๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํšŒ์›๊ฐ€์ž… ๋ฐ ๋กœ๊ทธ์ธ P1 ์ด์œ ์ง„ โญ•๏ธ
์ž๋™๋กœ๊ทธ์ธ P2 ์ด์œ ์ง„ โญ•๏ธ
ํ‚ค์›Œ๋“œ ์„ค์ • ํ‚ค์›Œ๋“œ ์„ ํƒ P1 ์žฅํ˜œ๋ น โญ•๏ธ
ํ‚ค์›Œ๋“œ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œ P1 ์žฅํ˜œ๋ น โญ•๏ธ
ํ‚ค์›Œ๋“œ ์šฐ์„ ์ˆœ์œ„ ์ง€์ • P1 ์žฅํ˜œ๋ น โญ•๏ธ
ํ‚ค์›Œ๋“œ ์ •์˜ ์ž‘์„ฑ P1 ์žฅํ˜œ๋ น โญ•๏ธ
๊ธฐ๋ก ๊ธฐ๋ก ๋‚ ์งœ๋ณ„ ์กฐํšŒ P1 ์ด์œ ์ง„ โญ•๏ธ
ํ‚ค์›Œ๋“œ ๋ณ„ ๊ธฐ๋ก ์ถ”๊ฐ€ P1 ์ด์œ ์ง„ โญ•๏ธ
๊ธฐ๋ก ์ƒ์„ธ ํŽ˜์ด์ง€ P1 ์ด์œ ์ง„ โญ•๏ธ
๊ธฐ๋ก ์ˆ˜์ • ๋ฐ ์‚ญ์ œ P1 ์ด์œ ์ง„ โญ•๏ธ
๊ธฐ๋ก ๋‚ ์งœ ๋ณ€๊ฒฝ P1 ์ด์œ ์ง„ โญ•๏ธ
๋ชฉํ‘œ ๋ชฉํ‘œ ์ฃผ์ฐจ๋ณ„ ์กฐํšŒ P2 ์ด์œ ์ง„ โญ•๏ธ
๋ชฉํ‘œ ์ƒ์„ธ ํŽ˜์ด์ง€ P2 ์ด์œ ์ง„ โญ•๏ธ
ํ‚ค์›Œ๋“œ ๋ณ„ ๋ชฉํ‘œ ์ถ”๊ฐ€ P2 ์ด์œ ์ง„ โญ•๏ธ
๋ชฉํ‘œ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ P2 ์ด์œ ์ง„ โญ•๏ธ
๋ชฉํ‘œ ๋‹ฌ์„ฑ์—ฌ๋ถ€ ์ฒดํฌ P2 ์ด์œ ์ง„ โญ•๏ธ
๋ชฉํ‘œ ์ฃผ์ฐจ ๋ณ€๊ฒฝ P2 ์ด์œ ์ง„ โญ•๏ธ
ํšŒ๊ณ  ๋ฆฌํฌํŠธ ์กฐํšŒ P1 ์‹ ์œค์•„ โญ•๏ธ
ํ‚ค์›Œ๋“œ ๋ณ„ ๋ฆฌํฌํŠธ ์กฐํšŒ P1 ์‹ ์œค์•„ โญ•๏ธ
ํšŒ๊ณ  ์กฐํšŒ P1 ์‹ ์œค์•„ โญ•๏ธ
ํšŒ๊ณ  ์ž‘์„ฑ P1 ์‹ ์œค์•„ โญ•๏ธ
ํšŒ๊ณ  ์ฃผ์ฐจ ๋ณ€๊ฒฝ P1 ์‹ ์œค์•„ โญ•๏ธ
๋งˆ์ดํŽ˜์ด์ง€ ํ‚ค์›Œ๋“œ ์šฐ์„ ์ˆœ์œ„ ๋ณ€๊ฒฝ P2 ์žฅํ˜œ๋ น โญ•๏ธ
ํ‚ค์›Œ๋“œ ์ •์˜ ์กฐํšŒ P2 ์žฅํ˜œ๋ น โญ•๏ธ
ํ‚ค์›Œ๋“œ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œ P2 ์žฅํ˜œ๋ น โญ•๏ธ
๊ธฐ๋ก ํ‚ค์›Œ๋“œ ๋“ฑ๋ก ๋ฐ ํ•ด์ œ P2 ์žฅํ˜œ๋ น โญ•๏ธ
์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ P3 ์‹ ์œค์•„ โญ•๏ธ
๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ P3 ์‹ ์œค์•„ โญ•๏ธ
ํšŒ์›ํƒˆํ‡ด P3 ์‹ ์œค์•„ โญ•๏ธ

โœ… ๊ฐœ๋ฐœ ์„ค๋ช…

  1. ํ•ต์‹ฌ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

    • ํ‚ค์›Œ๋“œ ์„ค์ •

       //KeywordSettingTVC - tableviewcell ์•ˆ์— ๋ฒ„ํŠผ ํด๋ฆญ delegate
           protocol SelectKeywordDelegate {
             func addSelectedKeyword(_ cell: KeywordSettingTVC, selectedText: String) -> Bool
      
             func cancelSelectedKeyword(_ cell: KeywordSettingTVC, selectedText: String)
           }
      
           }
      
       ///KeywordSettingVC
           extension KeywordSettingVC: SelectKeywordDelegate{
             func addSelectedKeyword(_ cell: KeywordSettingTVC, selectedText: String) -> Bool{
                 if selectedKeywordCount >= 8{
                     alertKeyword()
                     return false
                 }else{
                     if attitudeOfWork.contains(selectedText){
                         selectedKeywordList[1].append(selectedText)
                     }else{
                         selectedKeywordList[0].append(selectedText)
                     }
                     selectedKeywordCount += 1
                     setButtonActive()
                     return true
                 }
             }
      
             func cancelSelectedKeyword(_ cell: KeywordSettingTVC, selectedText: String) {
                 var keywordIndex = -1
      
                 for i in 0...2{
                     keywordIndex = selectedKeywordList[i].firstIndex(of: selectedText) ?? -1
                     if keywordIndex != -1{
                         selectedKeywordList[i].remove(at: keywordIndex)
                         selectedKeywordCount -= 1
                         setButtonActive()
                     }
                 }
             }
         }

      tableview cell ์•ˆ์— ํ‚ค์›Œ๋“œ ๋ฒ„ํŠผ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ, ๊ทธ ๋ˆŒ๋ฆฌ ๋ฒ„ํŠผ์˜ ์ด๋ฆ„์ด ๋ฌด์—‡์ด์—ˆ๋Š”์ง€, ํ˜„์žฌ ๋ˆŒ๋ฆฐ ๋ฒ„ํŠผ์€ ๋ช‡๊ฐœ์ธ์ง€๋ฅผ ์•Œ์•„์•ผํ–ˆ๋‹ค. ๋‹ค๋ฅธ ๊ณ„์ธต์˜ ๋ทฐ ์‚ฌ์ด์˜ ์ •๋ณด๋ฅผ ์ฒ˜์Œ์—๋Š” ์–ด๋–ป๊ฒŒ ์ฃผ๊ณ  ๋ฐ›์„์ง€ ๋ชฐ๋ผ static ๋ณ€์ˆ˜๋กœ ๋ˆŒ๋ฆฐ ๊ฐฏ์ˆ˜๋ฅผ +,- ํ–ˆ๋‹ค. ๊ทธ static ๋ณ€์ˆ˜๊ฐ€ 8๊ฐœ๊ฐ€ ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ delegate๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•˜์˜€๋‹ค. ํ•˜์œ„ ๋ทฐ์— cell์— delegate ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ƒ์œ„์ธ VC์—์„œ ๊ตฌํ˜„ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์•˜๋‹ค.

    • ๊ธฐ๋ก

      @IBAction func btnMoreTapped(_ sender: Any) {
              if sender is UIButton {
                  isExpanded = !isExpanded
                  
                  sizingLabel.numberOfLines = isExpanded ? 0 : 1
                  labelBody.textColor = isExpanded ? UIColor.mainLightGray3 : UIColor.white
                  labelBody.font = .myRegularSystemFont(ofSize: 15)
                  sizingLabel.font = .myRegularSystemFont(ofSize: 15)
                  buttonMore.setImage(isExpanded ? UIImage(named: "btn_chevron_down"): UIImage(named: "btn_chevron_up"), for: .normal)
                  
                  delegate?.moreTapped(cell: self)
              }
          }
      
       func moreTapped(cell: DetailTVC) {
              tableView.beginUpdates()
              tableView.endUpdates()
          }

      ๊ธฐ๋ก์˜ ๊ฐœ์ˆ˜์— ๋งž๊ฒŒ ๋“œ๋กญ๋‹ค์šด์ด ๋˜๋ฉฐ ์ •๋ณด๊ฐ€ ๋ณด์—ฌ์ ธ์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์—์„œ ํ…Œ์ด๋ธ”๋ทฐ์˜ ๊ธธ์ด๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€ํ–ˆ์–ด์•ผ ํ–ˆ๋‹ค. ํƒญ์ด ๋ˆŒ๋ฆฌ๋ฉด tableview๊ฐ€ ๋ ˆ์ด์•„์›ƒ์„ ๋‹ค์‹œ ์žก์„ ์ˆ˜ ์žˆ๊ฒŒ ๋™์ ์ธ ๊ธธ์ด๋ฅผ ๊ฐฑ์‹ ๋˜์–ด์•ผ ํ•ด์„œ ํ…Œ์ด๋ธ”๋ทฐ์˜ ๊ธธ์ด๋Š” estimatedRowHeight๋กœ ์ดˆ๊ธฐ์— ์žก๊ณ  automaticDimension์„ ์ ์šฉ์‹œ์ผœ์ฃผ์–ด ๊ตฌํ˜„ํ–ˆ๋‹ค.

    • ํšŒ๊ณ 

      func collectionView(_ collectionView: UICollectionView, heightForLabelAtIndexPath indexPath: IndexPath) -> CGFloat {
              let width = (collectionView.bounds.size.width - (collectionView.contentInset.left + collectionView.contentInset.right + 16 + 16 + 30)) / 2 - 30
              let label: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
              label.text = taskTitle[indexPath.item]
              label.preferredMaxLayoutWidth = width
              label.numberOfLines = 0
              label.lineBreakMode = NSLineBreakMode.byWordWrapping
              label.contentMode = .scaleToFill
              label.font = .myBoldSystemFont(ofSize: 16)
              label.sizeToFit()
              
              let calculateHeight = label.intrinsicContentSize.height + 120
              return calculateHeight
          }

      ํšŒ๊ณ ๋ทฐ์—์„œ ํ‚ค์›Œ๋“œ๋ณ„ ๋ฆฌํฌํŠธ ์ƒ์„ธ ๊ธฐ๋ก์„ ์กฐํšŒํ•  ์‹œ ํ•ด๋‹น ํ–‰๋™ ๊ธฐ๋ก text๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Label ํฌ๊ธฐ์— ๋”ฐ๋ผ ์…€์˜ height ํฌ๊ธฐ๊ฐ€ ๊ฐ๊ฐ ๋‹ค๋ฅธ UICollectionView๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ UICollectionViewLayout ํŒŒ์ผ์„ ๋”ฐ๋กœ ์ƒ์„ฑํ•ด collectionView์˜ ๋†’์ด๋ฅผ ์ƒ์„ฑํ•˜๋Š” collectionView ํ•จ์ˆ˜๋ฅผ overrideํ•˜์—ฌ Label์— ๋”ฐ๋ผ์„œ ์…€ ํฌ๊ธฐ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜ collectionView๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜์—์„œ๋Š” ๋“ค์–ด๊ฐ€๋Š” Label์˜ ๋†’์ด๋ฅผ ๊ณ„์‚ฐํ•ด๋‚ด์–ด ๊ฐ ์…€๋งˆ๋‹ค ๋‹ค๋ฅธ ๋†’์ด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

  2. Extension์„ ํ†ตํ•ด ์ž‘์„ฑํ•œ ๋ฉ”์†Œ๋“œ ์„ค๋ช…

    • Extension+Date

      extension Date {
          var startOfWeek: Date? {
              var gregorian = Calendar(identifier: .gregorian)
              gregorian.timeZone = TimeZone(secondsFromGMT: 0)!
              guard let monday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
              if Calendar.current.component(.weekday, from: monday) == 1{ //์ผ์š”์ผ์ผ๋•Œ
                  return gregorian.date(byAdding: .day, value: 1, to: monday)
              }else{
                  return gregorian.date(byAdding: .day, value: 2, to: monday)
              }
          }
          
          var endOfWeek: Date? {
              var gregorian = Calendar(identifier: .gregorian)
              gregorian.timeZone = TimeZone(secondsFromGMT: 0)!
              guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
              if Calendar.current.component(.weekday, from: self) == 1{ //์ผ์š”์ผ์ผ๋•Œ
                  return gregorian.date(byAdding: .day, value: 2, to: sunday)
              }else{
                  return gregorian.date(byAdding: .day, value: 7, to: sunday)
              }
          }
      }

      ์„œ๋ฒ„์™€์˜ ํ†ต์‹ ์—์„œ ํ˜„์žฌ ์‹œ์  ์ฃผ์ฐจ์˜ ์‹œ์ž‘๋‚ ์งœ์™€ ๋งˆ์ง€๋ง‰๋‚ ์งœ๋ฅผ ์œ ๋‹‰์Šคํƒ€์ž„์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

      iOS์—์„œ ์ œ๊ณต๋˜๋Š” Calendar๋Š” ๋งค์ฃผ ์ผ์š”์ผ์„ ์ฃผ์˜ ์‹œ์ž‘์œผ๋กœ ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›”์š”์ผ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ•˜๋Š” ํฌ๋ชจ์ŠคํŠธ์—๋Š” ๋งž์ง€ ์•Š์•„ ์ผ์š”์ผ์ธ ๊ฒฝ์šฐ๋ฅผ ์˜ˆ์™ธ์ ์œผ๋กœ ๊ณ„์‚ฐํ•ด์„œ ํ˜„์žฌ ์‹œ์ ์˜ ์‹œ์ž‘๊ณผ ๋ ๋‚ ์งœ๋ฅผ ๋ฆฌํ„ด!


๐Ÿค 4Mosts Code Convention Rule

๋„ค์ด๋ฐ

  • ํ•จ์ˆ˜

      func set4Most() {
      } 
      lowerCamelCase ์‚ฌ์šฉํ•˜๊ณ  ๋™์‚ฌ๋กœ ์‹œ์ž‘
  • ๋ณ€์ˆ˜

      var fourMostMembers = 13
      lowerCamelCase ์‚ฌ์šฉ
  • ์ƒ์ˆ˜

      let fourMostiOSDevelopers: [String] = ["์œ ์ง„", "์œค์•„", "ํ˜œ๋ น"]
      lowerCamelCase ์‚ฌ์šฉ
  • ํด๋ž˜์Šค

      class fourMost{
      }
      UpperCamelCase ์‚ฌ์šฉ
  • ํŒŒ์ผ๋ช…

    ์•ฝ์–ด
    ViewController VC
    TableViewCell TVC
    CollectionViewCell CVC
  • ๋ฉ”์„œ๋“œ

    • ์„ค์ • ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋Š” set์œผ๋กœ ์‹œ์ž‘
        func setNavigationBar() {
        }

๊ธฐํƒ€๊ทœ์น™

  • self๋Š” ์ตœ๋Œ€ํ•œ ์‚ฌ์šฉ์„ ์ง€์–‘

  • viewDidLoad()์—์„œ๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ๋งŒ

    • delegate ์ง€์ •, UI๊ด€๋ จ ์„ค์ • ๋“ฑ๋“ฑ ๋ชจ๋‘ ํ•จ์ˆ˜๋กœ
  • ํ•จ์ˆ˜๋Š” extension์— ์ •์˜ํ•˜๊ณ  ์ •๋ฆฌ

    • extension์€ ๋ชฉ์ ์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜

๐ŸŽ 4Mosts Team Rule

git

๐Ÿ”€ git branch

  • master : ์ œํ’ˆ์œผ๋กœ ์ถœ์‹œ๋  ์ˆ˜ ์žˆ๋Š” ๋ธŒ๋žœ์น˜
  • develop : ๋‹ค์Œ ์ถœ์‹œ ๋ฒ„์ „์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ธŒ๋žœ์น˜
  • feature : ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ธŒ๋žœ์น˜
  • release : ์ด๋ฒˆ ์ถœ์‹œ ๋ฒ„์ „์„ ์ค€๋น„ํ•˜๋Š” ๋ธŒ๋žœ์น˜

โœŒ๏ธ git commit message

  • [Feat] : ๊ธฐ๋Šฅ์ถ”๊ฐ€
  • [Fix] : ๋ฒ„๊ทธ์ˆ˜์ •
  • [Chore] : ๊ฐ„๋‹จํ•œ ์ˆ˜์ •
  • [Docs] : ๋ฌธ์„œ ๋ฐ ๋ฆฌ๋“œ๋ฏธ ์ž‘์„ฑ
  • [Merge] : ๋จธ์ง€

project foldering

  • Resourse : asset, info.plist, AppDelegate ๊ด€๋ฆฌ

  • Source : Scene(flow ๋ณ„๋กœ ํด๋”๋ง) -> Storyboard, VC, Network(API), Model ๋“ฑ ๊ด€๋ฆฌ

    4Most_iOS
      |โ”€โ”€ Source
      โ”‚   โ””โ”€โ”€ Scene
      โ”‚         โ”œโ”€โ”€ MyDaily.storyboard
      โ”‚         โ”œโ”€โ”€ View
      โ”‚         โ”‚     โ”‚โ”€โ”€ Cell
      โ”‚         โ”‚     โ””โ”€โ”€ VC
      โ”‚         โ””โ”€โ”€ Network
      โ”‚               โ””โ”€โ”€ Service
      โ”‚               โ””โ”€โ”€ Response
      โ”‚               โ””โ”€โ”€ Resquest
      โ””โ”€โ”€ Resource 
         |โ”€โ”€ Assets.xcassets
         |โ”€โ”€ LaunchScreen.storyboard
         |โ”€โ”€ AppDelegate.swift
         |โ”€โ”€ SceneDelegate.swift
         โ””โ”€โ”€ Info.plist