# 주스메이커 STEP2 - 이번 미션을 진행하면서 새로 알게된 내용을 위주로 정리한 오늘의 TIL ### IBAction 한가지로 여러 버튼 관리하기 - **문제점** 주스를 주문했을 때 일어나는 메서드는 주스이름만 다를뿐 기능은 동일했다. 처음엔 주스별로 다 하나씩 코드를 작성하여 코드의 길이가 길어지는 문제가 있었고 중복되는 부분을 어떻게 이어주면 좋을지 고민해보았다. ![](https://i.imgur.com/HN6bsY0.png) - ```@IBAction```메서드를 정의하여 관리하고자 하는 버튼들을 다 연결시킨다. ![](https://i.imgur.com/wxLIWX3.png) - ```Tag```에 번호를 입력하여 각 버튼에 번호를 지정해준다. ```swift @IBAction private func orderJuiceButtonTapped(_ sender: UIButton) { switch sender.tag { case 1: completeOrder(of: .strawberryBananaJuice) case 2: completeOrder(of: .mangoKiwiJuice) case 3: completeOrder(of: .strawberryJuice) case 4: completeOrder(of: .bananaJuice) case 5: completeOrder(of: .pineappleJuice) case 6: completeOrder(of: .kiwiJuice) case 7: completeOrder(of: .mangoJuice) default: print("선택오류") ``` - switch 구문을 사용하여 tag의 번호에 따라 값을 입력했다. - 이런식으로 하나로 묶어서 관리하면 중복된 함수를 줄일 수 있고, 보다 깔끔하게 코드를 작성할 수 있다. - 근데....숫자를 쓰는 매직넘버까지는 생각 안해봤는데 ????? 로완 TIL 읽고 아차 싶었다 🙃 ### IBOutlet collection > @IBOutlet 변수들을 하나로 묶어 배열로 표현할 수 있다. - UILabel, UIButton 등 IBOutlet으로 표현하는 변수들을 하나의 collection 으로 묶어줄 수 있다. - 모든 변수에 같이 변화를 주고싶을 때 사용하면 좋다. ### singleton 적용 - **문제점** 과일재고를 담고 있는 ```FruitStore```를 싱글톤으로 구현했다. 그런데 초기재고 값이 빈배열로 확인되는 문제가 있었다. - 수정 전 코드 ```swift= final class FruitStore { static let sharedFruitStore = FruitStore() private init() {} var fruitStocks: [Fruit: Int] = [:] init(initialStock: Int = 10) { Fruit.allCases.forEach { fruitStocks[$0] = initialStock } } ``` - 위와같이 코드를 작성했을 때, private init() { }이 생성되어 빈 배열로 값이 입력된 문제가 있었다. - 수정 후 코드 ```swift final class FruitStore { static let sharedFruitStore = FruitStore(initialStock: 10) private init() {} var fruitStocks: [Fruit: Int] = [:] init(initialStock: Int) { Fruit.allCases.forEach { fruitStocks[$0] = initialStock } } ``` - 따라서 이를 방지하고자 초기 싱글톤을 구현할 때 ```initialStock : 10``` 을 입력하여 초기 값을 넣어주었다. ### 연산프로퍼티 적용 - 과일주스를 열거형으로 정의하였고 연산프로퍼티를 적용하여 과일주스의 이름을 입력해주었다. - 이와 같은 방법으로 오류 열거형도 정리해보았다. ```swift enum JuiceMakerError: Error { case outOfStock case fruitError var message: String { switch self { case .outOfStock: return "재고가 부족합니다." case .fruitError: return "과일 선택 오류입니다." } } } ``` - 읽기전용의 연산프로퍼티로 코드를 수정하였고 이때는 ```var message : String``` 과 같은 변수 생성이 필요했다. - 오류를 처리하는 출력문을 연산프로퍼티에서 바로 print로 찍어서 표현 하는 방법으로 접근을 했었는데 그렇게 하면 잘못된 접근이였다. 오류를 처리하는 곳에서 ```return``` 값을 받아오려면 ```print(JuiceMakerError.outOfStock.message)```로 접근할 수 있었다. ### navigation controller - 왜 navigation controller가 두개가 있을까? 궁금했다. 일단 두개가 있어서 카키가 없애지말고 연결시켜서 해보자 해서 우선 연결은 했는데 재고 수정을 눌렀을 때 화면이 바뀌고 다시 닫기를 누르면 주문 화면으로 넘어오고 기능적으로 버튼을 연결시키는 것과 크게 다른점을 느끼지 못했다. - navigation controller를 사용하는 것은 결국 화면과 화면을 분리한다고 생각하면 좋을 거 같다. ![](https://i.imgur.com/g2Z5E8S.png) - 공식문서에서 나와있는 내용을 정리해보면, navigation controller는 navigation interface에 있는 뷰 컨트롤러를 담당하는 역할을 가진다. - navigation controller가 할당되어 있다면 그것과 연결되어 있는 화면에 대한 내용은 한 navigation controller에만 쌓이게 된다. - 과제로 생각하면 주문하는 화면과 재고수정하는 화면은 각각 다른 navigation controller로 연결되어 있기 때문에 각각 다르게 관리되어진다. 별개의 흐름으로 인식하게 된다! - 결국은 개발자가 어떤 관점으로 바라보고 있느냐에 따라 navigation controller로 연결을 할지 아니면 하나의 화면에서 버튼으로 연결을 시킬지 결정하면 된다 ## 참고 [navigation controller](https://developer.apple.com/documentation/uikit/uinavigationcontroller)