---
# System prepended metadata

title: 주스메이커 STEP2

---

# 주스메이커 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)
