์ถ์ฒ ๋ฐ ์ฐธ๊ณ ์ฌ์ดํธ https://axiomatic-fuschia-666.notion.site/Chapter-3-TCA-2-c56b24efb2154dad9ed8e54139247024 Chapter 3. TCA์ ๊ธฐ๋ณธ๊ฐ๋
(2) ์์ ์ฅ์์ ์ฐ๋ฆฌ๋ ์ฑ์ ์ํ๋ฅผ ๋ํ๋ด๋ State์ ์ด๋ฅผ ๋ณ๊ฒฝํ ์๋จ์ธ Action, ๊ทธ Action์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์ํ์ ๋ณ๊ฒฝ์ ์ฒ๋ฆฌํ๋ Reducer์ ์์๋ณด๋ฉฐ, TCA์์์ ๋ฐ์ดํฐํ๋ฆ์ ๋ํด์ ์ดํด๋ณด์์ต๋ axiomatic-fuschia-666.notion.site Effect๋? Action์ด ๋ฐํํ๋ ํ์
์ ๋ปํ๋ฉฐ Action์ ๊ฑฐ์น ๋ชจ๋ ๊ฒฐ๊ณผ๋ฌผ์ ์๋ฏธํ๋ค. ๋น๋๊ธฐ ์์
์ด๋ ์ธ๋ถ ์์ฉ์ ์ํด ๋ฐ์ํ๋ Side Effect๋ ์ด๋ค ์ฒ๋ฆฌ ์ดํ ์์์น ๋ชปํ๊ฒ ์ป์ ๊ฒฐ๊ณผ๋ฌผ์..
์ ์ฒด ๊ธ
UIKit์ผ๋ก ๊ฐ๋ฐํ๋ค๊ฐ ํ์ฌ๋ SwiftUI๋ก ์๋น์ค ๊ฐ๋ฐํ๊ณ ์๋ Fram์ ๋๋ค SwiftUI์ Combine์ ๋ํด ์๊ฒ ๋ ๊ฒ๊ณผ ๊ธฐ์ ์ ๊ณต์ ํ๋ ๋ธ๋ก๊ทธ ์ ๋๋ค. ์ฃผ์ : ์ ์๋๊ฑฐ ๋ ์ ์ ์ ์์ํ๋ฆฌ๋ทฐ์์ not building -Onone๋ก ๋ก๋๊ฐ ์๋๋ฉด Edit Scheme ๋๋ฅด๊ณ Build Configuration ์์ Debug๋ก ๋ณ๊ฒฝํด์ฃผ์ธ์ ํ
์คํธ ํ๋ค๊ณ ์ ์ ๋ฐ๊ฟจ๋ค๊ฐ ๊น๋จน๊ณ ํ๋ฆฌ๋ทฐ ์ผ๋ ์๋์ ๋นํฉ;; ํ๋ฆฌ๋ทฐ ๋๋์ฒด ์ด๋ป๊ฒ ๊ตฌํ๋์ด ์๋๊ฑด์ง ์ ๊ธฐ
.overlay( Rectangle() .stroke(PWColor.gray100, lineWidth: 1) ) // .border(PWColor.gray100, width: 1) ์๋border์ ์ฌ์ฉํ๋ฉด frame์ผ๋ก ์ธ์ํ๊ฒ ๋จ. ํด๋น ์์ญ ๊น์ง ์กํ์ VStack์ผ๋ก ์์ผ๋ฉด ์ค๊ฐ์ 2๊ฐ ๋จ
TCA๋ฅผ ๊ณต๋ถํ๋ค๊ฐ Timer ์์๋ก ๋ฌด์์ ๊ตฌํํ๋ฉด ์ข์๊น ์๊ฐํด ๋ดค๋๋ ์ผํ๋ชฐ ์ฑ์ด ๋ ์ค๋ฅด๋๋ผ๊ตฌ์! ์ค๋ ์์ ๊น์ง์ ๋จ์ ์๊ฐ์ ๊ณ์ฐํด์ ์ค๋์ด ์ง๋๋ฉด ๊ตฌ๋งคํ ์ ์๋๋ก ๋ฒํผ์ ๋นํ์ฑํ ์ํฌ๊ฑฐ์์. ํ์ด๋จธ๋ฅผ ํ์ํ๋ ์ ๋ถ๋ถ์ด ๊ตฌ๋งค ๋ฒํผ์
๋๋ค. ๊ตฌํํด ๋๊ณ ๋ณด๋ ํ์ด๋จธ UI์ ๊ตฌ๋งคํ๊ธฐ ๋ฒํผ์ ๋ณ๋๋ก ๋ถ๋ฆฌํ ๊ฑธ ๊ทธ๋ฌ์ด์ ๐ฅฒ State struct State: Equatable { var isTimerOn = false var leftTime = "00:00:00" var isBuyButtonDisabled = true } isTimerOn์ด true๊ฐ ๋๋ฉด ํ์ด๋จธ๋ฅผ ์์ํ๊ณ false๊ฐ ๋๋ฉด ํ์ด๋จธ๋ฅผ cancel ์์ผ์ค๋๋ค. leftTime์ ๋ฒํผ ์์ญ์ ์๊ฐ ๋ถ๋ถ์ ํ์๋ ์คํธ๋ง ๊ฐ์ด์์. isBuy..
์ฐธ๊ณ ์ฌ์ดํธ https://axiomatic-fuschia-666.notion.site/Chapter-1-Hello-TCA-70c56437681547d4b85cd1363a157356 Chapter 1. Hello, TCA ์๋
ํ์ธ์. Swift๋ก Apple ์ํ๊ณ ๊ฐ๋ฐ์ ์ผ์กฐํด ์ฃผ์๋ ๊ฐ๋ฐ์ ์ฌ๋ฌ๋ถ, ๋ชจ๋ ๋ฐ๊ฐ์ต๋๋ค! axiomatic-fuschia-666.notion.site https://www.pointfree.co/collections/tours/composable-architecture-1-0/ep243-tour-of-the-composable-architecture-1-0-the-basics Episode #243: Tour of the Composable Architecture: The Ba..
์ด์ ์ ์ด๋ ์๋น์ค์์๋ ๊ทธ๋ฌ์ง๋ง ๊ฐ์
์ ๋ฐ์์ผ ํ๋ ์๋ฅ ์ค ์๊ธฐ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋ค. ์ด๋ฒ ์๋น์ค ๋ํ ์ต๋ 5๊ฐ์ ์๋ฅ๋ฅผ ๋ฐ์์ผ ํ๊ณ , ๊ทธ ์๋ฅ๊ฐ ์ ํจํ์ง ์๊ธฐ๋ก ๊ฒ์ฆ ํ์ ๊ฐ์
์ํฌ ์ ์๋ค๊ณ ํ๋ค. ์ฒจ๋ถ ํ ์ฌ์ฉ์๊ฐ ๋ณ๋๋ก ํ์ธํ๋ ๊ฒ์ด ์๋ ์ฒจ๋ถ๋จ- ์ํ ํ์ ํ ๋์ด๊ธฐ ๋๋ฌธ์, ์ฌ์ฉ์๊ฐ ๊ฐค๋ฌ๋ฆฌ์์ ํฐ์น ํ๋ฒ ์ ๋ชป ํด์ ์ด์ํ ์ฌ์ง์ด ๋ค์ด๊ฐ๋ฉด ์ ๋ฐฉ๋ฒ์ด ์๋ค. ์ด ํ CS์์๋ ์ฌ์ฉ์์ ์ฐ๋ฝํ๊ณ ์์ ํ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๋ค. ์์ ํ VisionKit์๊ฒ ๋งก๊ธฐ๋ ๊ฒ์ ๋ฌด๋ฆฌ์ด๊ฒ ์ง๋ง, ๊ธ์๋ฅผ ์ถ์ถํด์ ์์ฌ์ค๋ฌ์ด ์๋ฅ๋ ์ผ๋ฟ ์ฐฝ ํ๋ฒ ๋์์ ์ธ์ ์์ผ์ฃผ๋ ๊ฒ๋ ๋์์ง ์๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. CS ํ ์
๋ฌด๋ฅผ ์กฐ๊ธ ์ค์ฌ๋ค์ผ ์ ์์ง ์์๊น?! ์ ํ์์ ์ง์ํ๋ VisionKit์ผ๋ก ํ
์คํธ๋ฅผ ์ธ์..
์๋ฌด๋ฆฌ ๋ด๋ ํญ ๋ฐ๊ฐ ๋ง๋๊ฑฐ ๊ฐ์๋ฐ ๋์์ธํ์ด ํ ๊ธ์ด๋ผ ํ๋ ์ฐ์ ํ ๊ธ์ธ๊ฑธ๋ก..!! ๋ญ 2๊ฐ๋ฉด ํ ๊ธ ๋ง์ง! ์๋ฒ๋ก ๋ถํฐ ๋ช ๊ฐ๊ฐ ์ฌ์ง ๋ชจ๋ฅด๊ณ , ํด๋น ์์ญ์ ํญํ์ ๋ ํ ๊ธ ์ ๋๋ฉ์ด์
์ด ์คํ๋์ผ ํ๋ค. Namespace๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์
์ ๊ตฌํํ ์ ์๋ค. ๋ฌผ๋ก animation ์ ์ฌ์ฉํด๋ ๋๋ค! ์ฒ์์ GeometryReader๋ก ์์น๋ฅผ ๊ณ์ฐ ํ ๋ค ํ๋์ View์ ์์น๋ฅผ ๋ณ๊ฒฝํด ์ฃผ์๋๋ offset๊ณผ padding ์ผ๋ก ๋ทฐ ๊ณ์ธต์ ๋ฐ๊ฟจ์ ๋ ์ด์๊ฐ ์์๋ค. GeometryReader๋ก ๊ณ์ฐ ํ ์์น๊ฐ ๋ฌ๋ผ์ ธ์ ์๋ฑํ ๊ณณ์์ ๋ฐฑ๊ทธ๋ผ์ด๋๊ฐ ์์๋๊ณ ์์ง์๋ค. struct CustomToggle: View { let priceList = ["on", "off", "test"] /// ํ ๊ธ ..
struct TipBubbleShape: Shape, InsettableShape { private var insetValue = 0.0 func inset(by amount: CGFloat) -> some InsettableShape { var bubble = self bubble.insetValue = amount return bubble } func path(in rect: CGRect) -> Path { let width = rect.width let height = rect.height let radius = rect.height / 2.0 let midpoint = radius * 0.42 let path = Path { p in p.move(to: CGPoint(x: 25, y: height..