# ๐Ÿน ์บ ํผ๋“ค์˜ ๋ชฉ๋งˆ๋ฆ„์„ ์ฑ…์ž„์ง„๋‹ค! ์ฅฌ์Šค ๋ฉ”์ด์ปค ## ๐Ÿ“– ๋ชฉ์ฐจ 1. [ํŒ€ ์†Œ๊ฐœ](#-ํŒ€-์†Œ๊ฐœ) 2. [๊ธฐ๋Šฅ ์†Œ๊ฐœ](#-๊ธฐ๋Šฅ-์†Œ๊ฐœ) 3. [Diagram](#-Diagram) 4. [ํด๋” ๊ตฌ์กฐ](#-ํด๋”-๊ตฌ์กฐ) 5. [ํƒ€์ž„๋ผ์ธ](#-ํƒ€์ž„๋ผ์ธ) 6. [ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…](#-ํŠธ๋Ÿฌ๋ธ”-์ŠˆํŒ…) 7. [๊ธฐ์ˆ ์  ๋„์ „](#-๊ธฐ์ˆ ์ -๋„์ „) 8. [์ฐธ๊ณ  ๋งํฌ](#-์ฐธ๊ณ -๋งํฌ) ## ๐ŸŒฑ ํŒ€ ์†Œ๊ฐœ |[Wonbi](https://github.com/wonbi92)|[woong](https://github.com/iOS-Woong)| |:---:|:---:| | <img width="180px" img style="border: 2px solid lightgray; border-radius: 90px;-moz-border-radius: 90px;-khtml-border-radius: 90px;-webkit-border-radius: 90px;" src="https://avatars.githubusercontent.com/u/88074999?v=4">| <img width="180px" img style="border: 2px solid lightgray; border-radius: 90px;-moz-border-radius: 90px;-khtml-border-radius: 90px;-webkit-border-radius: 90px;" src="https://avatars.githubusercontent.com/u/96489602?v=4">| - `Wonbi`์™€ `woong` ํŒ€์ด ๋งŒ๋“  ์ฅฌ์Šค ๋ฉ”์ด์ปค์ž…๋‹ˆ๋‹ค. ## โš’๏ธ ๊ธฐ๋Šฅ ์†Œ๊ฐœ |**์ฃผ์Šค ์ฃผ๋ฌธํ™”๋ฉด**|**์žฌ๊ณ  ์ˆ˜์ • ํ™”๋ฉด**| |:---:|:---:| |![](https://i.imgur.com/pEexHat.png)|![](https://i.imgur.com/Kn9saKC.png)| |**์ฃผ๋ฌธ ์„ฑ๊ณต(alert)**|**์ฃผ๋ฌธ ์‹คํŒจ(alert)**| |![](https://i.imgur.com/YQFHlMg.gif)|![](https://i.imgur.com/KQxT7zK.gif)| |**์žฌ๊ณ ์ˆ˜์ • ์ด๋™(alert์„ ํ†ตํ•œ ์ด๋™)**|**์žฌ๊ณ ์ˆ˜์ • ์ด๋™(button์„ ํ†ตํ•œ ์ด๋™)**| |![](https://i.imgur.com/UedTJUE.gif)|![](https://i.imgur.com/exjbEaf.gif) | |**์žฌ๊ณ ์ˆ˜์ • ์ ์šฉ(์ ์šฉ๋ฒ„ํŠผ)**|**์žฌ๊ณ ์ˆ˜์ • ์ทจ์†Œ(์ทจ์†Œ๋ฒ„ํŠผ)**| |![](https://i.imgur.com/CVodTQk.gif)|![](https://i.imgur.com/QfJUT8E.gif)| ## ๐Ÿ‘€ Diagram ### ๐Ÿงฌ Class Diagram ![JuiceMaker ClassDiagram](https://i.imgur.com/DOguFss.jpg) ### ๐Ÿงฌ Flow Chart ![JuiceMaker Flow Chart](https://i.imgur.com/WyO9bG8.png) ## ๐Ÿ—‚ ํด๋” ๊ตฌ์กฐ > Modal : ์•ฑ ๊ตฌ๋™ ๋กœ์ง์— ํ•„์š”ํ•œ ๋ชจ๋ธ > View : ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ทฐ > Controller : ํ™”๋ฉด์˜ ์ด๋ฒคํŠธ์™€ ์ „ํ™˜์„ ์ปจํŠธ๋กคํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ ![](https://i.imgur.com/MC0mnDp.png) ## โฐ ํƒ€์ž„๋ผ์ธ ### ๐Ÿ‘Ÿ Step 1 - class ํƒ€์ž…์˜`FruitStore` ๊ตฌํ˜„ - struct ํƒ€์ž…์˜ `JuiceMaker`๊ตฌํ˜„ - enum ํƒ€์ž…์˜ `Juice`๊ตฌํ˜„ - enum ํƒ€์ž…์˜ `Fruit`๊ตฌํ˜„ - error๋ฅผ ์ฑ„ํƒํ•œ enum ํƒ€์ž…์˜ `StockError`๊ตฌํ˜„ <details> <summary>Details</summary> <div markdown="1"> #### **220829** - `Fruit` - ํƒ€์ž… ์ผ€์ด์Šค ๊ตฌํ˜„ - `FruitStore` - ์˜ ์žฌ๊ณ  ์ฒดํฌ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ - ์žฌ๊ณ  ๊ฐœ์ˆ˜ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ, ํŒจํ„ด ๊ตฌํ˜„ - `StockError` - ์—๋Ÿฌ ์ผ€์ด์Šค ๊ตฌํ˜„ #### **220830** - `Juice` - ํƒ€์ž… ์ผ€์ด์Šค ๊ตฌํ˜„ - `FruitStore` - `JuiceMaker`์—๊ฒŒ ๊ณผ์ผ์„ ์ „๋‹ฌํ•˜๋Š” ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ - ๋ฉ”์„œ๋“œ ๋กœ์ง ๋ณ€๊ฒฝ ๋ฐ ์ปจ๋ฒค์…˜ ์ˆ˜์ • - `JuiceMaker` - ์ฃผ์Šค ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ - ํ”„๋กœํผํ‹ฐ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • - ์ปจ๋ฒค์…˜ ์ˆ˜์ • #### **220831** - ๋ฉ”์„œ๋“œ ๋ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ฆฌํŒฉํ† ๋ง - ๋ฒ„๊ทธ ์ˆ˜์ • - `Fruit` - ํƒ€์ž… ์žฌ์ •์˜ - `FruitStore` - ์žฌ๊ณ  ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ์ˆ˜์ • - ์žฌ๊ณ ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ์ˆ˜์ • - ๊ณผ์ผ์„ ์ „๋‹ฌํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ์ˆ˜์ • #### **220901** - ๋ฉ”์„œ๋“œ ๋ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ฆฌํŒฉํ† ๋ง - `Fruit` - ํƒ€์ž… ์žฌ์ •์˜ - `FruitStore` - ์‹ฑ๊ธ€ํ†ค ์‚ญ์ œ - ์žฌ๊ณ ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋ฆฌํŒฉํ† ๋ง - `JuiceMaker` - ์ฅฌ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ์ˆ˜์ • - `StockError` - ์‚ญ์ œ #### **220902** - ๋ฉ”์„œ๋“œ ๋ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ฆฌํŒฉํ† ๋ง - `Recipe` - ํƒ€์ž… ์ผ€์ด์Šค ๊ตฌํ˜„ - `FruitStore` - ์ด๋‹ˆ์…œ๋ผ์ด์ € ๋กœ์ง ์ˆ˜์ • - ์žฌ๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ์ˆ˜์ • #### **220904** - `Recipe` - ์‚ญ์ œ - `Juice` - ์žฌ๋ฃŒ์™€ ํ•„์š”๊ฐฏ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํ”„๋กœํผํ‹ฐ ์ถ”๊ฐ€ </div> </details> ### ๐Ÿ‘Ÿ Step 2 - `MainViewController` ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ๋กœ์ง ๊ตฌํ˜„ - `EditViewController` ์ƒ์„ฑ - `EditView` ์˜คํ† ๋ ˆ์ด์•„์›ƒ ์„ค์ • - ๋ชจ๋‹ฌ ๋ฐฉ์‹์˜ ํ™”๋ฉด์ „ํ™˜ ๊ตฌํ˜„ <details> <summary>Details</summary> <div markdown="1"> #### **220905** - ์„ธ๊ทธ์›จ์ด ๋ฐฉ์‹์œผ๋กœ ํ™”๋ฉด ์ „ํ™˜๊ตฌํ˜„ - `MainViewController` - ๋ฒ„ํŠผ ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ - ๊ฒฐ๊ณผ์— ๋งž๋Š” Alert ๊ตฌํ˜„ - ๋ทฐ์˜ ๋ ˆ์ด๋ธ”๊ณผ ๋ชจ๋ธ ๋‚ด๋ถ€์˜ ์žฌ๊ณ ๊ฐ’์„ ์—ฐ๊ฒฐ - `EditViewController` - ์ƒ์„ฑ - ์˜คํ† ๋ ˆ์ด์•„์›ƒ ์„ค์ • - ์ทจ์†Œ ๋ฒ„ํŠผ ๊ตฌํ˜„ #### **220906** - ์ฝ”๋“œ ๋„ค์ด๋ฐ ๋ฆฌํŒฉํ† ๋ง - ์ฝ”๋“œ๋ฅผ ํ†ตํ•œ ํ™”๋ฉด์ „ํ™˜ ๋ฐฉ์‹์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง - `MainViewController` - `NotificationCenter`๋ฅผ ํ†ตํ•ด ์žฌ๊ณ  ๋ณ€๊ฒฝ์‹œ๋งˆ๋‹ค ํ™”๋ฉด ๋ ˆ์ด๋ธ”์— ๋™๊ธฐํ™”๋˜๋„๋ก ๊ตฌํ˜„ - ์ฃผ๋ฌธ ๋ฒ„ํŠผ์„ ์‹๋ณ„ํ•˜๋Š” ๋กœ์ง ๊ตฌํ˜„ #### **220907** - `MainViewController` - KVO๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์žฌ๊ณ ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋กœ์ง ๊ตฌํ˜„ #### **220908** - `MainViewController` - KVO๋ฅผ ํ†ตํ•ด Alert์„ ๋„์šฐ๋„๋ก ๋ฆฌํŒฉํ† ๋ง - ํ™”๋ฉด ์ „ํ™˜ ์‹œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ์œ„ํ•œ `StockStorage`ํƒ€์ž…์„ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ - ์ฃผ๋ฌธ ๋ฒ„ํŠผ์„ ์‹๋ณ„ํ•˜๊ณ  ์ฃผ๋ฌธ์ด ์„ฑ๊ณตํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ๋ถ„๋ฆฌ #### **220912** - ๋„ค์ด๋ฐ ๋ฆฌํŒฉํ† ๋ง, ์†Œ์ŠคํŒŒ์ผ ์ •๋ฆฌ - `MainViewController` - KVO ์ œ๊ฑฐ - ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ „๋‹ฌํ•˜๋„๋ก ๋ฆฌํŒฉํ† ๋ง </div> </details> ### ๐Ÿ‘Ÿ Step 3 - `EditViewController` ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ๋กœ์ง ๊ตฌํ˜„ - `AlertMessage`๋„ค์ž„ ์ŠคํŽ˜์ด์Šค ๊ตฌํ˜„ - Alert ๋ฉ”์„œ๋“œ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ - ๊ฐ์ฒด ์บก์Аํ™” <details> <summary>Details</summary> <div markdown="1"> #### **220913** - ์˜คํ† ๋ ˆ์ด์•„์›ƒ ์ ์šฉ - `Response` - ๋„ค์ž„ ์ŠคํŽ˜์ด์Šค enumํƒ€์ž… ๊ตฌํ˜„ - `EditViewController` - `Stepper`์˜ `value`๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ - `Stepper` ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ๋กœ์ง ๊ตฌํ˜„ - `FruitStore` - ์žฌ๊ณ  ๋ณ€๊ฒฝํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋กœ์ง ๋ฆฌํŒฉํ† ๋ง #### **220915** - `AlertMessage` - ํƒ€์ž… ๋ช…์„ `Response`์—์„œ `AlertMessage`๋กœ ๊ต์ฒด - Alert์— ๊ด€๋ จ๋œ ๋ชจ๋“  ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ - `EditViewController` - `Stepper` ์ด๋ฒคํŠธ์— ๋Œ€์‘ํ•˜๋Š” ๋กœ์ง ๋ฆฌํŒฉํ† ๋ง - Alert ๋ฉ”์„œ๋“œ ํ•˜๋‚˜๋กœ ํ†ตํ•ฉ #### **220916** - `EditViewController` - ๋‚ด๋ถ€ ํ”„๋กœํผํ‹ฐ `stock`์„ `FruitStore` ๋‚ด๋ถ€๋กœ ์บก์Аํ™” </div> </details> ## ๐Ÿƒ๐Ÿป ๊ธฐ์ˆ ์  ๋„์ „ [์‹ฑ๊ธ€ํ†ค](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#%EF%B8%8F-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4) [NotificationCenter](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#%EF%B8%8F-notificationcenter) [KVOํŒจํ„ด](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#%EF%B8%8F-kvo-%ED%8C%A8%ED%84%B4) [DelegateํŒจํ„ด](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#%EF%B8%8F-delegate-%ED%8C%A8%ED%84%B4) ## ๐Ÿš€ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… [ํ™”๋ฉด ์ „ํ™˜์‹œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#-%ED%99%94%EB%A9%B4-%EC%A0%84%ED%99%98%EC%8B%9C-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%84%EB%8B%AC) [Alert ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋กœ ํ†ตํ•ฉ ๊ด€๋ฆฌ](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#-alert-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%97%AC%EB%9F%AC%EA%B0%9C%EB%A1%9C-%EB%B6%84%EB%A6%AC%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%B4-%EC%95%84%EB%8B%8C-%ED%95%98%EB%82%98%EC%9D%98-%ED%95%A8%EC%88%98%EB%A1%9C-%ED%86%B5%ED%95%A9-%EA%B4%80%EB%A6%AC) [FruitStore์— ์ž„์‹œ์žฌ๊ณ ๋ฅผ ๊ตฌํ˜„ํ•จ์œผ๋กœ์จ ์บก์Аํ™”](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#-fruitstore%EC%97%90-%EC%9E%84%EC%8B%9C%EC%9E%AC%EA%B3%A0%EB%A5%BC-%EA%B5%AC%ED%98%84%ED%95%A8%EC%9C%BC%EB%A1%9C%EC%8D%A8-%EC%BA%A1%EC%8A%90%ED%99%94) [rawValue์˜ ์‚ฌ์šฉ](https://github.com/wonbi92/ios-juice-maker/wiki/%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85-&-%EA%B8%B0%EC%88%A0%EC%A0%81-%EB%8F%84%EC%A0%84#-rawvalue%EC%9D%98-%EC%82%AC%EC%9A%A9) ## ๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ [Swift API Design Guidelines - Naming](https://swift.org/documentation/api-design-guidelines/) [Swift Language Guide - Initialization](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html) [Swift Language Guide - Access Control](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html) [Swift Language Guide - Nested Types](https://docs.swift.org/swift-book/LanguageGuide/NestedTypes.html) [Swift Language Guide - Type Casting](https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html) [Swift Language Guide - Error Handling](https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html) --- [๐Ÿ” ๋งจ ์œ„๋กœ ์ด๋™ํ•˜๊ธฐ](#-์ฅฌ์Šค-๋ฉ”์ด์ปค) 1. ์‹ฑ๊ธ€ํ†ค 2. NotificationCenter 3. KVO 4. Delegate 5. Data Send From Method 6. ์บก์Аํ™”? ### ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ํ™œ์šฉ ```swift class FruitStore { static var stockManager = FruitStore() var stock: [Fruit: Int] = Fruit.defaultStock private init() {} } struct JuiceMaker { let stockManager = FruitStore.stockManager func requestFruit() -> Int { let numberOfFruits = stockManager.stock[.strawberry] return numberOfFruits } } ``` ์ฒ˜์Œ์— ๊ณผ์ผ์„ ์ €์žฅํ•˜๊ณ ์žˆ๋Š” FruitStore ํด๋ž˜์Šค์˜ ์ฒ˜๋ฆฌ๋ฅผ `์‹ฑ๊ธ€ํ†คํŒจํ„ด`์„ ํ™œ์šฉํ•˜์—ฌ ๊ณผ์ผ์˜ ์ˆ˜๋Ÿ‰์„ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ชจ๋“  ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ ํ˜น์€ ๋ชจ๋ธ์—์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„ ํ•˜๋ ค๊ณ  ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์‹ฑ๊ธ€ํ†ค ์ธ์Šคํ„ด์Šค์— ๋„ˆ๋ฌด ๋งŽ์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋  ๊ฒฝ์šฐ์— ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์งˆ ๊ฒƒ์„ ์šฐ๋ คํ–ˆ๊ณ , ์—ฌ๋Ÿฌ๊ตฐ๋ฐ์—์„œ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์ ‘๊ทผํ•˜์—ฌ ๊ฐ’์„ ๋ฐ”๊พธ๊ฒŒ ๋  ๊ฒฝ์šฐ ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ๊ฒƒ์ด๋ฏ€๋กœ ์ด ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•˜์ง€ ์•Š๊ณ , FruitStore์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ, ๊ฐ ํƒ€์ž… ๋‚ด์—์„œprivate์œผ๋กœ FruitStore๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์ „์—ญ ์ ‘๊ทผ์„ ์ฐจ๋‹จํ•˜์—ฌ ์•ˆ์ „ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค. ### NotificationCenter ```swift // MainViewController private func settingObserver() { NotificationCenter.default.addObserver(self, selector: #selector(updateStockCount(_:)), name: .changedStockCount, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(madeJuiceAlert(_:)), name: .madeJuiceAlert, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(failedAlert(_:)), name: .failedAlert, object: nil) } // JuiceMaker func makeJuice(_ juice: Juice) { if store.canSupplyRequest(ingredient: juice.ingredient) { NotificationCenter.default.post(name: .madeJuiceAlert, object: nil, userInfo: ["JuiceName" : juice.name]) } else { NotificationCenter.default.post(name: .failedAlert, object: nil) } } } // FruitStore private(set) var stock: [Int] { didSet { NotificationCenter.default.post(name: .changedStockCount, object: nil, userInfo: nil) } } ``` - ์žฌ๊ณ ๊ฐ€ ์ˆ˜์ •๋  ๋•Œ๋งˆ๋‹ค ์ˆ˜์ •๋œ ์žฌ๊ณ ๋ฅผ ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š” ๋กœ์ง๊ณผ ์ฅฌ์Šค ์ œ์กฐ์˜ ์„ฑ๊ณต ์‹คํŒจ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋กœ์ง์„ `NotificationCenter`๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. - `NotificationCenter`์˜ ์žฅ์ ์€ ์ฝ”๋”๊ฐ€ ์›ํ•˜๋Š” ์‹œ์ ์— ์˜ต์ €๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์•Œ๋ฆผ์„ ๋ฐœ์†กํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋‹ค๋ฅธ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋‚˜ ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•˜์ง€ ์•Š๊ณ  ์™„์ „ํžˆ ๋ถ„๋ฆฌ๋œ ์ƒํƒœ์—์„œ๋„ ํฌ์ŠคํŒ…๋œ ์ •๋ณด๋“ค์„ ์˜ต์ €๋ฒ„๋ฅผ ํ†ตํ•ด ๋ฐ›์•„๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ ์ด ์žฅ์ ์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. - ํ•˜์ง€๋งŒ, `NotificationCenter`๋Š” ๋”ฐ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š๋Š”์ด์ƒ ์•ฑ ๋‚ด์— ๋ชจ๋“  ๋ถ€๋ถ„์— post๋ฅผ ๋‚ ๋ฆฌ๋Š” ๋กœ์ง์œผ๋กœ ๊ตฌํ˜„๋˜์–ด์žˆ๊ณ , ์‹ฌ์ง€์–ด ๋‹ค๋ฅธ ๋ชจ๋“ˆ์—๋„ post๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์•ฑ์˜ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ์•ฑ ์ „์ฒด ํ˜น์€, ๋‹ค๋ฅธ ์•ฑ์— "์•Œ๋ฆฌ๋Š”" ๊ฐ์ฒด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. - ์˜ˆ๋ฅผ ๋“ค์–ด, ํ•ธ๋“œํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ์ค‘์— ์ „ํ™”๊ฐ€ ์˜ค๋ฉด, `NotificationCenter`๋ฅผ ํ†ตํ•ด ์ „ํ™”๊ฐ€ ์ˆ˜์‹ ๋˜์—ˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๋ฆฌ๊ณ , ๊ทธ์— ๋งž๊ฒŒ ์‚ฌ์šฉ์ค‘์ธ ์•ฑ์ด ์ผ์‹œ์ •์ง€๋˜๋„๋ก ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์ด๋ผ ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. - ์ด๋Ÿฌํ•œ ์ด์œ  ๋•Œ๋ฌธ์— `NotificationCenter`๋Š” ์ตœ์ข…์ ์œผ๋กœ ์ฑ„ํƒํ•˜์ง€ ์•Š๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ### KVO ```swift // FruitStore class FruitStore: NSObject { @objc dynamic private(set) var stock: [Int] } // MainViewController class MainViewController: UIViewController { @objc let store = FruitStore(stockCount: 10) override func viewDidLoad() { super.viewDidLoad() stockChangeObserver = observe(\.store.stock, options: [.new, .initial], changeHandler: { (object, stock) in guard let newStock = stock.newValue else { return } self.updateStockCount(stock: newStock) }) } } ``` - ๋˜ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ์˜ ๋ณ€ํ™”๋ฅผ ์ฒดํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ KVO ํŒจํ„ด์„ ํ†ตํ•ด ์žฌ๊ณ ๊ฐ€ ์ˆ˜์ •๋  ๋•Œ ๋งˆ๋‹ค ์ˆ˜์ •๋œ ์žฌ๊ณ ๋ฅผ ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. - KVO์˜ ์žฅ์ ์€ ๋‘ ๊ฐ์ฒด๊ฐ„ ์ •๋ณด๋ฅผ ๋™๊ธฐํ™” ํ•˜๋Š”๊ฒƒ์ด ๋งค์šฐ ์‰ฝ๋‹ค๋Š” ๊ฒƒ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. - ํ•˜์ง€๋งŒ, ๋ฐ˜๋“œ์‹œ ๊ทธ ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ๋งŒ ๋ฐ์ดํ„ฐ์˜ ์ถ”์ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๊ณ  `NSObject`๋ฅผ ์ƒ์† ๋ฐ›์•„ Objective-C ๋Ÿฐํƒ€์ž„์„ ์ด์šฉํ•ด ๊ฐ’์„ ์ถ”์ ํ•˜๊ธฐ์— ๊ฐ„๋‹จํ•œ ๊ฐ’ ๋ณ€ํ™”๋ฅผ ์œ„ํ•ด ์ด๋ ‡๊ฒŒ๊นŒ์ง€ ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์˜๋ฌธ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. - ๊ฒŒ๋‹ค๊ฐ€ KVO์˜ ์žฅ์ ์œผ๋กœ ๋งŽ์ด๋“ค ๊ฑฐ๋ก ํ•˜๋Š” `Nasted Type`์˜ ๊ฐ’ ๋ณ€ํ™”๋„ ์ถ”์ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ๋„ ์ €ํฌ์˜ ์•ฑ์—์„œ๋Š” ๊ตณ์ด ์žฅ์ ์œผ๋กœ ์ž‘์šฉํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. - ๊ฒฐ๋ก ์ ์œผ๋กœ, ๊ฐ„๋‹จํ•œ ๊ฐ’ ๋ณ€ํ™”๋ฅผ ์˜ต์ €๋น™ ํ•˜๊ธฐ์œ„ํ•ด ๋งŽ์€ ์ฝ”๋“œ์ค„๊ณผ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค ํŒ๋‹จ๋˜์–ด ์ฑ„ํƒํ•˜์ง€ ์•Š์•˜๊ณ , ๊ฐ’์ด ๋ณ€ํ™”ํ•˜๋Š” ๊ฒฝ์šฐ์— ์žฌ๊ณ ๋ฅผ ํ™”๋ฉด์— ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ### DelegateํŒจํ„ด ```swift //editViewController - ์ฑ„ํƒ ๋ฐ ์š”๊ตฌ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ extension EditViewController: SendDataDelegate { func sendStock(_ stock: [Int]) { self.stock = stock } } //ViewController - ํ”„๋กœํ† ์ฝœ ์„ ์–ธ ๋ฐ ํ”„๋กœํผํ‹ฐ ์ƒ์„ฑ protocol SendDataDelegate: AnyObject { func sendStock(_ stock: [Int]) } class MainViewController: UIViewController { weak var delegate: SendDataDelegate? @IBAction private func tappedModifyBarButton(_ sender: Any) { // EditViewController๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•จ. delegate = editViewController delegate?.sendStock(store.stock) present(editViewController, animated: true) } } ``` ์ตœ์ดˆ์˜ ์„ค๊ณ„์—์„  ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง์ ‘ ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ์— ์ ‘๊ทผํ•ด data๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋‹ค๋ฅธ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์˜ ํ”„๋กœํผํ‹ฐ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๊ณ  ํ•ด๋‹น ์ปจํŠธ๋กค๋Ÿฌ์— ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ํ˜•ํƒœ์ž„๊ณผ ๋™์‹œ์— ํ”„๋กœํผํ‹ฐ์— ์ง์ ‘์ ‘๊ทผ์„ํ•˜๊ฑฐ๋‚˜ ์ง์ ‘ ๊ฐ’์„ ์„ค์ •ํ•˜๊ธฐ์— ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง„๋‹ค๊ณ  ํŒ๋‹จํ–ˆ๊ณ , ์œ„ ์‚ฌํ•ญ์ด ์šฐ๋ ค๋˜์–ด `Delegate`๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋„๋ก ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์ „์†กํ•˜๋Š” ๋กœ์ง์— `Delegate`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๊ณ  ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋งŽ์ด ํ•ด์นœ๋‹ค ํŒ๋‹จํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ๋Š” ์ฑ„ํƒํ•˜์ง€ ์•Š์•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ฃผ๊ณ ๋ฐ›๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ### ํ™”๋ฉด ์ „ํ™˜์‹œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ```swift // MainViewController class MainViewController: UIViewController { private let store = FruitStore(stockCount: 10) private lazy var juiceMaker = JuiceMaker(store: store) @IBAction private func tappedModifyBarButton(_ sender: Any) { // EditViewController๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•จ. editViewController.setStore(from: store) present(editViewController, animated: true) } } // EditViewController class EditViewController: UIViewController { private var store: FruitStore? func setStore(from store: FruitStore) { self.store = store } } ``` - ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์˜ ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ™”๋ฉด ์ „ํ™˜์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•˜์˜€๊ณ  ๊ทธ์ค‘์— ์ €ํฌ๊ฐ€ ์ตœ์ข…์ ์œผ๋กœ ์ฑ„ํƒํ•œ ๋ฐฉ๋ฒ•์€ "๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ"๋ฐฉ์‹ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. - ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฐฉ๋ฒ•๋“ค ์—ญ์‹œ ์žฅ๋‹จ์ ์ด ์žˆ์—ˆ์ง€๋งŒ, ๊ฐ€๋ฒผ์šด ๋ฐ์ดํ„ฐ ํ•˜๋‚˜๋ฅผ ๋„˜๊ธฐ๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๊ธฐ๋„ ํ•˜๊ณ , ์‚ฌ์šฉ์‹œ ์žฅ์ ๋ณด๋‹ค๋Š” ๋‹จ์ ์ด ๋” ๋ถ€๊ฐ๋˜๋Š”๊ฑฐ ๊ฐ™์•„ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๋ฉด์„œ๋„ ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. - `FruitStore`๋Š” `class`์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ฐธ์กฐ ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ `MainViewController`์—์„œ `EditViewController`๋ฅผ `present`ํ•˜๊ธฐ ์ „์— `EditViewController`์˜ ํ”„๋กœํผํ‹ฐ `store`๊ฐ€ `MainViewController`์˜ `store`๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. - ์ด ๊ฒฐ๊ณผ ์•ฑ์—๋Š” ์—ฌ์ „ํžˆ ํ•˜๋‚˜์˜ `store`๋งŒ ์กด์žฌํ•˜๊ฒŒ ๋˜์–ด ๊ฐ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ , ์žฌ๊ณ ์˜ ๋ฌด๊ฒฐ์„ฑ์„ ์ง€์ผฐ์œผ๋ฉฐ, ๋‚˜์•„๊ฐ€ ์žฌ๊ณ ์˜ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋ทฐ์˜ ๋ณ€ํ™”๋„ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ### FruitStore์— ์ž„์‹œ์žฌ๊ณ ๋ฅผ ๊ตฌํ˜„ํ•จ์œผ๋กœ์จ ์บก์Аํ™” ```swift // FruitStore class FruitStore { private(set) var stock: [Int] private(set) var queuedStock = [Int]() func setQueuedStock() { queuedStock = stock } func changeQueueStock(fruitIndex: Int, count: Int) { queuedStock[fruitIndex] = count } func confirmChange() { stock = queuedStock queuedStock = [Int]() } } // EditViewController class EditViewController: UIViewController { private var store: FruitStore? @IBAction private func tappedCancelButton(_ sender: UIBarButtonItem) { dismiss(animated: true) } @IBAction private func tappedApplyButton(_ sender: UIButton) { store?.confirmChange() dismiss(animated: true) } @IBAction private func tappedStepper(_ sender: UIStepper) { let fruitIndex = sender.tag, newCount = sender.value fruitCountLabels?[fruitIndex].text = Int(newCount).description store?.changeQueueStock(fruitIndex: fruitIndex, count: Int(newCount)) } ``` - ๊ธฐ์กด ์ฝ”๋“œ์—์„œ๋Š” `EditViewController`์—์„œ ์ž„์‹œ ์žฌ๊ณ ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๊ทธ ์žฌ๊ณ ๋ฅผ '์ ์šฉ' ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์žฌ๊ณ ์— ์ ์šฉํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. - ํ•˜์ง€๋งŒ, `EditViewController`๊ฐ€ ์ž„์‹œ ์žฌ๊ณ ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ๊ฐ์ฒด์ง€ํ–ฅ์˜ "์บก์Аํ™”"์— ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ ์ด๋ฅผ `FruitStore`์—์„œ ์ง์ ‘ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋ฆฌํŒฉํ† ๋ง์„ ์ง„ํ–‰ํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. - ์ด ์—ญ์‹œ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„๋ก ํ•˜์—ฌ ๊ฒฐํ•ฉ๋„๋ฅผ ๋†’์ด์ง€ ์•Š์œผ๋ฉด์„œ ๊ฐ’์ด ๋ฐ”๋€Œ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ### rawValue์˜ ์‚ฌ์šฉ ```swift enum Juice: String { case strawberryJuice = "๋”ธ๊ธฐ ์ฃผ์Šค" case bananaJuice = "๋ฐ”๋‚˜๋‚˜ ์ฃผ์Šค" case kiwiJuice = "ํ‚ค์œ„ ์ฃผ์Šค" case pineappleJuice = "ํŒŒ์ธ์• ํ”Œ ์ฃผ์Šค" case mangoJuice = "๋ง๊ณ  ์ฃผ์Šค" case strawberryBananaJuice = "๋”ธ๋ฐ” ์ฃผ์Šค" case mangoKiwiJuice = "๋งํ‚ค ์ฃผ์Šค" var name: String { switch self { case .strawberryJuice: return "๋”ธ๊ธฐ ์ฃผ์Šค" case .bananaJuice: return "๋ฐ”๋‚˜๋‚˜ ์ฃผ์Šค" case .kiwiJuice: return "ํ‚ค์œ„ ์ฃผ์Šค" case .pineappleJuice: return "ํŒŒ์ธ์• ํ”Œ ์ฃผ์Šค" case .mangoJuice: return "๋ง๊ณ  ์ฃผ์Šค" case .strawberryBananaJuice: return "๋”ธ๋ฐ” ์ฃผ์Šค" case .mangoKiwiJuice: return "๋งํ‚ค ์ฃผ์Šค" } } } ``` - `enum`ํƒ€์ž…์˜ `rawValue`์‚ฌ์šฉ์€ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด `rawValue`๋ผ๋Š” ๋งค์ง ๋ฆฌํ„ฐ๋Ÿด์„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. - ๊ทธ๋ž˜์„œ ์ฒ˜์Œ์—๋Š” ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ด์šฉํ•ด `switch`๋ฌธ์œผ๋กœ `rawValue`๋ฅผ ํ™œ์šฉํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ๋งค์ง ๋ฆฌํ„ฐ๋Ÿด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒŒ ๋˜์–ด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ์˜ฌ๋ ค์ฃผ๊ธด ํ–ˆ์ง€๋งŒ, ์ฝ”๋“œ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ```swift enum Juice: String { case strawberryJuice = "๋”ธ๊ธฐ ์ฃผ์Šค" case bananaJuice = "๋ฐ”๋‚˜๋‚˜ ์ฃผ์Šค" case kiwiJuice = "ํ‚ค์œ„ ์ฃผ์Šค" case pineappleJuice = "ํŒŒ์ธ์• ํ”Œ ์ฃผ์Šค" case mangoJuice = "๋ง๊ณ  ์ฃผ์Šค" case strawberryBananaJuice = "๋”ธ๋ฐ” ์ฃผ์Šค" case mangoKiwiJuice = "๋งํ‚ค ์ฃผ์Šค" var name: String { self.rawValue } } ``` - ๊ทธ๋ฆฌ๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด.. ์•„๋ฆ„๋‹ต์Šต๋‹ˆ๋‹ค...โœจโœจ ์ด๋Ÿฐ ์ž‘์ง€๋งŒ ๊ธฐ๋ฐœํ•œ ์•„์ด๋””์–ด๊ฐ€ ์ฝ”๋“œ๋ฅผ ๋” ์ƒคํ”„ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ### Alert ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํ•˜๋‚˜์˜ ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„ ```swift private func resultAlert(isSuccess: Bool, juiceName: String = "") { let alert = UIAlertController(title: nil, message: isSuccess ? juiceName + AlertMesaage.successMesaage : AlertMesaage.failureMesaage, preferredStyle: .alert) let comfirmAction = UIAlertAction(title: isSuccess ? AlertMesaage.successConfirm : AlertMesaage.failureConfirm, style: .default, handler: isSuccess ? nil : { _ in self.tappedModifyBarButton(()) }) alert.addAction(comfirmAction) if !isSuccess { let noAction = UIAlertAction(title: AlertMesaage.failureCencel, style: .cancel) alert.addAction(noAction) } present(alert, animated: true) } ``` - ๊ธฐ์กด์—๋Š” `์‹คํŒจ๊ฒฝ์šฐ์˜ Alert` & `์„ฑ๊ณต๊ฒฝ์šฐ Alert`์˜ ๋ฉ”์„œ๋“œ๋กœ 2๊ฐœ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ฐ๊ฐ ๊ตฌํ˜„ํ•˜์—ฌ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ณ„๊ฐœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. - ํ•˜์ง€๋งŒ, ์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐ์„ฑ์„ ์œ„ํ•ด ๋กœ์ง๊ตฌํ˜„๋ถ€์—์„œ Bool ํƒ€์ž…์„ ์ „๋‹ฌ์ธ์ž๋กœ ๋ฐ›์•„ ์‹คํŒจ ํ•  ๊ฒฝ์šฐ์— UIAlertController์— noAction ๋ณ€์ˆ˜๊ฐ€ ์ถ”๊ฐ€๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.