@wongbingg
안녕하세요 웡빙~ step2 PR 보내드립니다.
이번 코드는 다소 난잡해 보이지만 리뷰 잘부탁드립니다😂
---
## 고민한 점
### ViewController의 ```fruitsStock``` 프로퍼티
- 값 타입? 참조 타입?
요구조건 "과일쥬스를 제조하여 과일의 재고가 변경되면 화면의 적절한 요소에 변경사항을 반영합니다." 를 구현할 때 문제점이 있었습니다.
```swift
// 수정 전
final class ViewController: UIViewController {
private let juiceMaker = JuiceMaker()
private var fruitsStock = FruitStore.shared.fruitsStock
override func viewDidLoad() {
super.viewDidLoad()
displayStock()
}
func displayStock() {
if let strawberryStock = fruitsStock[.strawberry],
... {
stockOfStrawberry.text = String(strawberryStock)
...
}
}
@IBAction func orderStrawberryBananaJuice(_ sender: UIButton) {
do {
try juiceMaker.make(juice: .strawberryBanana)
displayStock()
} catch ...
}
}
```
>```fruitsStock``` 변수에 ```FruitStore.shared.fruitsStock```을 할당했을 경우 화면에 변경사항이 반영되지 않았습니다.
값 타입의 특성을 잘 몰랐기 때문에 발생한 문제였다고 생각합니다.
>
>재고 초기값이 10인 상태로 ```fruitsStock```변수에 초기값이 복사되어있어 ```make```메서드를 통해 재고가 변경되어도 화면에는 그대로 10이 출력되었습니다.
>
>Swift의 Copy on Write에 대한 학습에 더불어 월요일 학습활동을 통해 값 타입과 참조 타입의 차이점을 알게 되었습니다.
```swift
// 수정 후
final class ViewController: UIViewController {
private let juiceMaker = JuiceMaker()
private var fruitsStock: [Fruits: Int] {
return FruitStore.shared.fruitsStock
}
override func viewDidLoad() {
super.viewDidLoad()
displayStock()
}
func displayStock() {
if let strawberryStock = fruitsStock[.strawberry],
... {
stockOfStrawberry.text = String(strawberryStock)
...
}
}
@IBAction func orderStrawberryBananaJuice(_ sender: UIButton) {
do {
try juiceMaker.make(juice: .strawberryBanana)
displayStock()
} catch ...
}
}
```
>```fruitsStock```을 연산 프로퍼티로 정의하여 해당 변수에 접근하는 시점에 재고 딕셔너리 값을 가져올 수 있도록 만들어 해결했습니다.
<br/>
## 해결이 되지 않은 점
재고수정과, Alert에서 동일한 화면으로 전환시키기 위해 똑같은 방법을 사용하였습니다. NavigationController에서 Push해주는 방법을 사용했을 때, 재고수정버튼을 누를 경우 오른쪽에서 슬라이딩되며 화면전환이 되는데, Alert을 통해 화면전환을 할 때는 부자연스럽게 화면전환이 됩니다.
어떤 문제점이 있는걸까요?
- 재고수정버튼을 통한 화면 이동
```swift
@IBAction func ClickChangeStock(_ sender: Any) {
moveToChangeStockViewController()
}
```

<br/>
- Alert을 통한 화면 이동
```swift
func setFailAlert() {
let failAlert = UIAlertController(title: "재료가 모자라요. 재고를 수정할까요?", message: nil, preferredStyle: UIAlertController.Style.alert)
let yesAction = UIAlertAction(title: "예",
style: UIAlertAction.Style.default,
handler: { Action in self.moveToChangeStockViewController() })
let noAction = UIAlertAction(title: "아니오", style: UIAlertAction.Style.default, handler: nil)
failAlert.addAction(yesAction)
failAlert.addAction(noAction)
present(failAlert, animated: true, completion: nil)
}
```

<br/>
## 조언을 얻고 싶은 점
### 쥬스 주문 버튼의 IBAction에서 반복되는 코드를 줄이는 방법
@IBAction 함수에서 매개변수를 받는 방법은 없는건지 궁금합니다! 🧐
밑에 코드에서 ```.strawberryBanana```를 받아올 수 있다면 ```do-catch```구문을 함수로 뺄 수 있을거 같습니다.
```swift=
@IBAction func orderStrawberryBananaJuice(_ sender: UIButton) {
do {
try juiceMaker.make(juice: .strawberryBanana)
setSuccessAlert(juiceName: .strawberryBanana)
displayStock()
} catch StockError.outOfStock {
setFailAlert()
} catch {
print(error)
}
}
```
22.01.09 월
할당 allocation: 프로그래밍에서는 '메모리를 나누어 쓰는 것'으로 생각하자.
물리적인 메모리는 전기 신호를 저장하기 위해 많은 공간을 갖고있고, 공간 식별을 위해 공간 별 주소를 갖는다.
OS가 바라보는 physical memory를 논리적 메모리라 하고
논리적 메모리에는 code, data, stack, heap이 있다.
Stack
- Stack pointer??
- 데이터 할당 -> 스택 포인터를 내린다.
- 데이터 할당 해제 -> 스택 포인터를 올린다.
- stack에 메모리 할당을 하게 되면 성능이 좋다.
- 선형 자료구조(다른 자료구조에 비해 쉽다 / 많이 사용된다)
- 스택 메모리의 크기는 컴파일 시점에 결정된다.
Heap
- 비선형 자료구조 (Advanced data structure)
- Tree 자료구조 중 heap이 있다. (Tree 구조)
- 자료 검색을 할 때 비용이 많이 발생한다.
- 힙 메모리에 할당을 위해 메모리에서 사용되지 않는 공간을 찾아야한다.
- 메모리에 올라간 데이터를 내릴 때, 다시 메모리 블록을 재삽입해야한다.
- 스레드 시간, 공간적 비용 (Thread safety overhead)
stack과 heap은 같은 메모리 공간을 활용한다.
stack은 높은 메모리 주소 공간에서 데이터를 쌓으면서 내려온다.
heap은 낮은 메모리 주소 공간에서 데이터를 쌓으면서 올라간다.(단순히 쌓이는 건 아님 복잡한 과정이 있다.)
Stack 영역의 데이터가 heap을 침범하면 stackoverflow가 발생.
Heap 영역의 데이터가 stack을 침범하면 heapoverflow가 발생.
메모리 주소 값이 숫자가 크면 High 낮으면 Low 주소이다.
Class / Struct 전 stack, heap memory에 대해 공부하는 이유?
CPU -> Memory에 직접 접근
CPU가 메모리를 읽는 것에 실패하게 되면, 앱을 강제종료하는 에러가 발생한다.
메모리의 적절한 처리가 필요함.
Struct Allocation
stack에는 변수들이 할당된다.
구조체의 값도 할당된다.
사용이 끝나면 메모리에서 내려감
class 내부에 구조체가 있는 경우 heap 메모리에 할당될 수도 있다.
Class Allocation
클래스의 인스턴스는 heap 메모리에 올라간다.
프로그램이 메모리에 올라간 상태 -> Process
Singleton = process에서 어떤 타입의 인스턴스가 단 하나만 존재하게 만드는 디자인패턴
- 컴파일 타임에 stack의 크기가 결정된다.
- 열거형, 구조체가 고정적인 메모리 크기를 갖고 있기 떄문에 가능하다.
- Heap은 가변적인 크기를 갖기 때문에 메모리 크기가 고정적이지 않은 것이 올라가게 된다.
Last in First out
-----