Giter Club home page Giter Club logo

ios-juice-maker's Introduction

🥤 쥬스 메이커

다양한 쥬스를 만들고 재고를 관리하는 어플


🔎 목차


👥 팀원

Kiseok🐶 쥬봉이🐱
GitHub GitHub

📅 타임라인

👥 팀프로젝트

날짜 내용
23.09.11 - 공식문서 공부
- 그라운드 룰 정하기
23.09.12 - juicemaker, fruitstore, fruit, juicemenu 타입 정의
- 쥬스 만드는 메소드, 과일 소모시키는 메소드 구현
- Step1 PR
23.09.15 - 과일 소모시키는 메소드 기능 분리
- 레시피 함수 -> 주스메뉴 열거형에 연산프로퍼티로 수정
- ReadMe 작성
23.09.18 - 재고 부족 에러 정의 및 처리
- 화면 전환 구현(네비게이션 방식)
- 쥬스 생성 완료 또는 재고 부족 alert 구현
23.09.19 - 화면 전환 방식 네비게이션 방식에서 모달로 수정
- Step2 PR
23.09.20 - 컨벤션 수정
- class에 final 키워드 추가
- 메세지 namespace 추가
23.09.21 - 오토레이아웃 설정
- stepper(-, +) 클릭시 화면 및 재고 수정 메서드 구현
- Step3 PR
23.09.22 - 재고 수정 메소드 수정
- ViewController의 IBOutlet을 collection으로 변경
- UI나타내는 메서드 수정, stepper 탭했을 때 메서드 수정
23.09.25 - 코드 리팩터링
23.09.26 - delegate pattern 구현
23.09.27 - UML 시각화 구조 작성
- ReadMe 최종 작성

🛠️ 리팩터

날짜 내용
23.11.09 - dynamic type 적용
- accessibilityLabel 수정
- UIAccessibility notification 적용

👀 시각화 구조

1. Sequence Diagram

스크린샷 2023-09-27 오후 2 04 42

2. Class Diagram

스크린샷 2023-09-27 오후 2 05 08

💻 실행화면

재고 수정 버튼 클릭 주문 성공
재고수정 버튼 주문 성공
주문 실패(재고 수정 예) 주문 실패(재고 수정 아니오)
재고수정 예 재고 부족 아니오

🔥 트러블 슈팅

  1. FruitStore의 decreaseStock메서드는 과일 재고를 확인하고 문제가 없으면 과일 수량을 낮추는 함수. 과일을 2개 소비해야할때 두 과일의 재고를 먼저 확인하고 수량을 낮추어주어야하는데, 이를 구현해보니 for-loop 2개를 사용하여 코드가 지저분해지는 문제 발생 -> 첫번째 for-in 루프가 isInvalidStock 함수와 기능이 비슷해 isInvalidStock으로 옮겨줌.
  • 수정 전 코드
func decreaseStock(fruits: [Fruit : Int]) -> Bool {
    for (fruit, quantity) in fruits {
        guard checkStock(fruit: fruit, quantity: quantity) else {
            return false
        }
    }

    for (fruit, quantity) in fruits {
        guard let stock = fruits[fruit] else {
            return false
        }
        self.fruits[fruit] = stock - quantity
    }

    return true
}
  • 수정 후 코드
func isValidStock(of recipe: [Fruit: Int]) -> Bool {
    for (fruit, quantity) in recipe {
        guard let stock = fruits[fruit], stock >= quantity else {
            return false
        }
    }

    return true
}

func decreaseStock(of recipe: [Fruit: Int]) {
    recipe.forEach { (fruit, quantity) in
        guard let stock = fruits[fruit] else { return }
        fruits[fruit] = stock - quantity
    }
}

  1. JuiceMakerViewController에서 StockChangeViewController로 바로 modal 연결을 했더니 navigation bar가 안나타나는 문제 발생 -> StockChangeViewController에 navigationController를 연결해준 후 modal을 navigationController를 호출하는 방식으로 변경
guard let stockNavigationController = self.storyboard?.instantiateViewController(
    withIdentifier: "StockChangeNavigationController"
) as? UINavigationController else {
    return
}

stockNavigationController.modalPresentationStyle = .fullScreen
self.present(stockNavigationController, animated: true)

  1. stepper 사용 시 아래와 같은 문제점들이 발생
    • stepper 초기값이 0으로 설정 -> stepper별 상이한 초기값을 어떻게 설정할지
    • label 값이 0보다 더 적어지는 문제
    • stepper 값이 (-)가 안되는 문제 -> 처음에 각 stepper의 초기값을 fruitStore의 재고로 설정하는 것으로 해결
// stepper 초기값 설정
private func setStepperValue() {
    Fruit.allCases.enumerated().forEach { (index, fruit) in
        stepperCollection[index].value = Double(fruitStore.fruits[fruit] ?? .zero)
    }
}

// label 값 설정
private func setupUI() {
    labelCollection.enumerated().forEach { (index, label) in
        label.text = String(changeStepperValueToInt(at: index))
    }
}

// stepper 클릭시 label 변경
@IBAction func stepperTapped(_ sender: UIStepper) {
    let index = sender.tag
    labelCollection[index].text = String(changeStepperValueToInt(at: index))
}

  1. IBOutlet Collection 사용 시 각 요소를 어떻게 구분하고 순서를 어떻게 확인해야할지 고민 -> didSet을 활용하여 각각의 tag값으로 순서를 정해줌
@IBOutlet var stepperCollection: [UIStepper]! {
    didSet {
        stepperCollection.sort { $0.tag < $1.tag }
    }
}

  1. 재고수정 후 delegate패턴으로 수정된 재고를 UI에 반영하기위해 JuiceMakerViewController에서 StockChangeViewController를 호출하려고 했으나 동작 안함 -> NavigationController를 새로 만들고 추가로 또 StockChangeViewController를 새로 만들다보니 완전히 다른 ViewController가 되어 delegate가 호출이 안됨 -> NavigationController호출 후 그 Controller의 topViewController를 불러오는 방법으로 StockChangeViewController 호출
  • 동작 안된 코드
private func pushToStockViewController() {
    guard let stockNavigationController = self.storyboard?.instantiateViewController(
        withIdentifier: "StockChangeNavigationController"
    ) as? UINavigationController else {
        return
    }

    guard let stockChangeViewController = self.storyboard?.instantiateViewController(
        withIdentifier: "StockChangeViewController"
    ) as? StockChangeViewController else {
        return
    }

    stockChangeViewController.delegate = self
    self.present(stockNavigationController, animated: true)
}
  • 수정 코드
private func pushToStockViewController() {
// (생략 부분 위와동일)

    guard let stockChangeViewController = stockNavigationController.topViewController
            as? StockChangeViewController else {
        return
    }

    stockChangeViewController.delegate = self
    self.present(stockNavigationController, animated: true)
}

📚 참고 링크

애플 공식문서 Hashable
애플 공식문서 CustomStringConvertible
애플 공식문서 UIViewController
애플 공식문서 forEach(_:)
애플 공식문서 Protocol
애플 공식문서 UIAccessibility


팀 회고

우리팀이 잘한 점
  • 핵심경험, 요구사항 반영 노력함
  • 피드백받은 사항에 대해 공부하고 적절히 개선함
우리팀이 개선할 점
  • 배려가 있는 모습은 좋으나 자기 주장과 자신감이 다소 부족함
서로에게 피드백
  • Kiseok: 구현 능력이 너무 뛰어나셔서 혼자 해결하지 못하는 부분들을 어려움없이 해결해 주시고 잘 알려주셨습니다.
  • 쥬봉이 : 제가 생각하지 못한 부분을 Kiseok이 많이 알고 있어 도움이 많이되고 배울 수 있었습니다. 덕분에 큰 트러블없이 프로젝트를 진행할 수 있었습니다.

ios-juice-maker's People

Contributors

jyubong avatar carti1108 avatar yagom avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.