SwiftUI๋ก ๊ฐ๋ฐ์ ์งํํ๋ค๊ฐ View ๋ด๋ถ์์ ์ง์ ์ ์ผ๋ก ํ๋กํผํฐ์ ์ ๊ทผํ ๋ onAppear๋ฅผ ํ ๋ฒ์ฏค์ ์ฌ์ฉํ ๊ฒฝํ์ด ์์ ๊ฒ์ด๋ค.
๊ฐ๋ น, print(ํ๋กํผํฐ)์ฒ๋ผ View ๋ด๋ถ์์ ์ ๊ทผํ๋ฉด ์ด๋ฐ ์๋ฌ๊ฐ ๋ฌ๋ค.
View๋ฅผ ๋ฐํํด๋ฌ๋ผ๋ ์๋ฌ๋ค.
์ด๋ฐ ์๋ฌ์ ๋ง์ฃผ์น์ง ์๊ธฐ ์ํด View ๋ด๋ถ์์ ์ง์ ์ ์ผ๋ก ์ ๊ทผํ์ง ์๊ณ , onAppear ํด๋ก์ ๋ด๋ถ์์ ์ ๊ทผํ๋ ๋ฐฉ์์ ํํ๋ค.
์๋ฌดํผ ์ด๋ด ๋ ์์ฃผ ์ฌ์ฉํ๋ onAppear๋ SwiftUI View Life Cycle์ ์ํ๊ณ , ์ค๋์ Life Cycle์ ๋ํด ์์๋ณด๋ ค๊ณ ํ๋ค.
SwiftUI์์ 3๊ฐ์ Life Cycle์ด ์๊ณ , ๊ฐ๊ฐ์ Appear, Update, Disappear ์ด๋ค.
1. onAppear
onAppear์ View๊ฐ ๋ณด์ฌ์ง๊ธฐ ์ ์ ํธ์ถ๋๋ค.
UIkit์ผ๋ก ์น๋ฉด viewWillAppear๋ผ๊ณ ์๊ฐํ๋๋ฐ ์๋ ๋งํฌ์์๋ viewDidAppear๋ผ๊ณ ์ค๋ช ํ๊ณ ์๋ค.
์ค์ ๋ก ๊ณต์ ๋ฌธ์์์๋ "before this view appears"๋ก ๋์์๊ณ , ๋ทฐ๊ฐ ๋ํ๋๊ธฐ ์ ์ด๋๊น willAppear๊ฐ ๋ง์ง ์์๊น ํ๋๋ฐ...
(์๊ณ ๊ฒ์ ๋ถ์ด ์์ผ์๋ฉด ๋์ ๋ถํ๋๋ฆฝ๋๋ค ใ
)
2. onDisappear
๊ทธ๋ ๋ค๋ฉด Disappear๋?
onAppear๊ณผ ๋ฐ๋๋ก View๊ฐ ์ฌ๋ผ์ง ๋ค์ ํธ์ถ๋๋ค.
์๊ฑด UiKit์์์ viewDidDisappear๋ผ๊ณ ์๊ฐํ๋ค. ์ฌ๋ผ์ง ๋ค์ ํธ์ถ๋๋ ๊ฑฐ๋๊น?
๊ทผ๋ฐ ๋ญ๊ฐ ์ด๋ ๊ฒ ์ธํธ๋ก ๋ง์์ผํ ๊ฒ ๊ฐ์๋ฐ
(SwiftUI) - (UIKit)
onAppear - viewWillAppear
onDisappear - viewWillDisappear
๋ด ์๊ฐ๋๋กํ๋ฉด ์ด๋ฐ ๋๋์ด๋ผ
(SwiftUI) - (UIKit)
onAppear - viewWillAppear
onDisappear - viewDidDisappear
์ ๋ง์ผ๋๊น ๋ถํธํ๋ค.
์ด ๋ถ๋ถ์ ์ข ๋ ์์๋ด์ผ๊ฒ ๋ค.
3. NavigationStack
Update์ ๋ํด์๋ ๋์ค์ ๋ค์ ํ ๋ฒ ์์๋ณด๋๋ก ํ๊ณ ...
์ฌ์ค ์ค๋์ ํน์ ๋ทฐ์ Life Cycle์ ์์๋ณด๋ค๊ฐ ์ ๊ธฐํด์ ์ ๋ ๊ธ์ด๋ค.
๋ญ๊ฐ ์ ํ์ด ์ผ์ด๋๊ฑฐ๋ ํน์ ๋ทฐ ์์ ์กด์ฌํ๋ ๋ทฐ์ธ NavigationStack - NavigationLink, ModalSheet, Alert.
์ด ์น๊ตฌ๋ค์ ๋ํด์ ์์๋ดค๋ค.
์ฐ์ ์ฒซ ๋ฒ์งธ๋ก, NavigationStack์์์ ์ธ์ ํธ์ถ๋๋์ง ์์๋ณด์.
import SwiftUI
// ์ฒซ ๋ฒ์งธ ๋ทฐ
struct FirstView: View {
var body: some View {
NavigationStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
}
// ๋ ๋ฒ์งธ ๋ทฐ
struct SecondView: View {
var body: some View {
NavigationLink(destination: ThridView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
.onAppear {
print("SecondView Appear")
}
.onDisappear {
print("SecondView Disappear")
}
}
}
// ์ธ ๋ฒ์งธ ๋ทฐ
struct ThridView: View {
var body: some View {
NavigationStack {
Text("์ธ ๋ฒ์งธ๊น์ง ์์ต๋๋ค.")
.onAppear {
print("ThirdView Appear")
}
.onDisappear {
print("ThirdView Disappear")
}
}
}
}
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์๊น ์์์ ๋ดค๋ Flow๋ฅผ ๊ทธ๋๋ก ์คํํ๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ ๊น?
์์์ ์๊ธฐํ๋ ๊ฒ์ฒ๋ผ onAppear๋ ๋ณด์ฌ์ง๊ธฐ ์ , onDisappear๋ ์ฌ๋ผ์ง ํ์ ํธ์ถ๋๋ค๊ณ ํ๋ค.
๊ทธ๋ ๋ค๋ฉด ๋ค์ View์ onAppear๊ฐ ๋จผ์ ์ถ๋ ฅ๋๊ณ ์ดํ์ ์ด์ View์ onDisappear๊ฐ ์ถ๋ ฅ๋์ง ์์๊น?
FirstView Appear
SecondView Appear
FirstView Disappear
ThirdView Appear
SecondView Disppear
ํ์ง๋ง ๊ฒฐ๊ณผ๋ ๋ฌ๋๋ค.
FirstView Disappear๊ฐ ์ถ๋ ฅ๋์ง ์์๋ค.
UI์์ ์ฌ๋ผ์ก๋๋ฐ onDisappear๊ฐ ์ถ๋ ฅ๋์ง ์๋๊ฒ ์ด์ํด์ ๋๋ฒ๊น ์ ์งํํ๊ณ , ์ค์ ๋ก UI Hierarchy๋ฅผ ์ถ๋ ฅํด๋ดค๋ค.
์ฌ์ง์ ๋ณด๋ฉด UIKitNavigationController์ NavigationStackHostingController๊ฐ ๋์ผํ๊ฒ ๋ฐฐ์น๋์ด ์๋ค.
NavigationLink๋ก ํ๋ฉด์ด ์ ํ๋๋, ๊ทธ ๊ธฐ๋ฐ์ ์ด๋ฃจ๋ NavigationStack(Controller)๋ ์ค์ ๋ก ๋ณด์ด์ง ์์ง๋ง ๊ทธ๋๋ก ์ ์ง๋๊ณ ์๊ธฐ์ onDisappear๊ฐ ํธ์ถ๋์ง ์์ ๊ฒ์ด์๋ค.
๊ทธ๋ ๋ค๋ฉด NavigationStack์ด ์๋, ๋ด๋ถ์ ์์นํ๊ณ ์๋ NavigationLink์ ์ ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
struct FirstView: View {
var body: some View {
NavigationStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
}
}
๋ญ๊ฐ, ์ด๋ฒ์ ์ ๋๋ก ๋์ํ ๊ฒ ๊ฐ๋ค๋ ๋๋์ด ๋ค์๋ค.
์ด๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ฒ์์ ์์ํ๋ ๊ฒ์ฒ๋ผ ์ถ๋ ฅ๋๋ค!
NavigationStack์์ onAppear๋ onDisappear๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ ๋๋ ๋ด๋ถ์ ์์นํ๊ณ ์๋ View์์ ์ ๊ทผํ๋ ๊ฒ์ด ์ข์ ๋ฏ ํ๋ค!
NavigationStack์ด ์ด๋ ๊ฒ ์๋ํ๋ ๊ฑธ ๋ณด๋๊น ๋ค๋ฅธ View๋ค๋ ๊ถ๊ธํด์ก๋ค.
4. Modal View
๊ทธ ๋ค์ ํ์๋, Modal View์๋ค.
Model View๋ ๋ค๋ฅธ View๊ณผ ํจ๊ป ์กด์ฌํ๋ฏ๋ก ๋ญ๊ฐ ์์๋ณด๊ณ ์ถ์๋ค.
struct FirstView: View {
@State private var isShow: Bool = false
var body: some View {
NavigationStack {
VStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
Button(action: {
isShow.toggle()
}) {
Text("๋ชจ๋ฌ ๊บผ๋ด๊ธฐ")
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
.sheet(isPresented: $isShow, onDismiss: {
print("ModalSheet Dismiss")
}) {
Text("๋? ๋ชจ๋ฌ")
}
.onAppear {
print("ModelSheet Appear")
}
.onDisappear {
print("ModelSheet Disappear")
}
}
}
}
Model View๊ฐ ๋ณด์ฌ์ง๊ณ ๋ซํ๋ Flow๋ฅผ ์คํํ๋ฉด ์ด๋ค ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ ๋ ๊น?
FirstView Appear
ModalSheet Appear
ModalSheet Dismiss
ModalSheet Disappear
ํ์ง๋ง ๋ฌ๋๋ค...
FirstView Appear๋ณด๋ค ModalSheet Appear๊ฐ ๋จผ์ ์ด๋ค์ก๊ณ Modal์ด ์ฌ๋ผ์ก์ ๋ Dismiss๋ง ํธ์ถ๋์ ๋ฟ, Disappear๋ ํธ์ถ๋์ง ์์๋ค.
UI Hierarchy์์ Modal์ด ์ฌ๋ผ์ค๊ธฐ ์ , ์ฌ๋ผ์ค๊ณ ๋ ํ์ ์ฐจ์ด๊ฐ ์์์๋ ModalSheet Appear๊ฐ Modal์ด ์ค์ ๋ก ์ฌ๋ผ์์ ๋ ์ถ๋ ฅ๋์ง ์๋ ์ด์ ์ ๋ํด์๋ ์์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค.
(์๊ณ ๊ฒ์ ๋ถ ์์ผ์๋ฉด ๋์ ๋ถํ๋๋ฆฝ๋๋ค ใ
)
๊ทธ๋์, ์ผ๋จ NavigationStack์ฒ๋ผ ๋ด๋ถ์ ์กด์ฌํ๋ View์ onAppear์ onDisappear๋ฅผ ๋ฌ์์คฌ๋ค.
struct FirstView: View {
@State private var isShow: Bool = false
var body: some View {
NavigationStack {
VStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
Button(action: {
isShow.toggle()
}) {
Text("๋ชจ๋ฌ ๊บผ๋ด๊ธฐ")
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
.sheet(isPresented: $isShow, onDismiss: {
print("ModalSheet Dismiss")
}) {
Text("๋? ๋ชจ๋ฌ")
.onAppear {
print("ModelSheet Appear")
}
.onDisappear {
print("ModelSheet Disappear")
}
}
}
}
}
๊ณผ์ฐ?
์ด๋ฒ์ ์ ์์ ์ผ๋ก ์๋ํ๋ค!
NavigationStack๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, Sheet์์ onAppear๋ onDisappear๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ ๋๋ ๋ด๋ถ์ ์์นํ๊ณ ์๋ View์์ ์ ๊ทผํ๋ ๊ฒ์ด ์ข์ ๋ฏ ํ๋ค!
5. Alert
๋ง์ง๋ง์ผ๋ก Alert, ์ด ์น๊ตฌ๋ ๊ถ๊ธํด์ก๋ค.
struct FirstView: View {
@State private var isShow: Bool = false
@State private var isAlert: Bool = false
var body: some View {
NavigationStack {
VStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
Button(action: {
isShow.toggle()
}) {
Text("๋ชจ๋ฌ ๊บผ๋ด๊ธฐ")
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
.sheet(isPresented: $isShow, onDismiss: {
print("ModalSheet Dismiss")
}) {
VStack {
Text("๋? ๋ชจ๋ฌ")
Button(action: {
self.isAlert.toggle()
}) {
Text("์๋ ๋์ฐ๊ธฐ")
}
.alert("์๋
", isPresented: $isAlert) {
Button("ํ์ธ") {}
} message: {
Text("๋? ์๋")
}
.onAppear {
print("Alert Appear")
}
.onDisappear {
print("Alert Disappear")
}
}
.onAppear {
print("ModelSheet Appear")
}
.onDisappear {
print("ModelSheet Disappear")
}
}
}
}
}
์ด๋ฒ์๋ ์์ ๋ดค๋ ๋ค๋ฅธ View๋ค์ฒ๋ผ ๋ง์ง๋ง์ modifer๋ฅผ ์ถ๊ฐํด์คฌ๋ค.
Alert์ด ๋ณด์ฌ์ง๋ View์ธ, Modal View๊ฐ ๋ณด์ฌ์ง ๋ Alert์ onAppear๋ ํธ์ถ๋๋ค.
์ญ์๋ ์ฐ๋ฆฌ์ ์๊ฐ๋๋ก ์์ง์ด์ง ์๋๋ค.
๊ทธ๋์ ๊ธฐ์กด์ View์ ๋ง์ง๋ง์ ์ถ๊ฐํด์คฌ๋ modifier๋ฅผ View์ ๋ด๋ถ๋ก ์ด๋์์ผฐ๋ค.
struct FirstView: View {
@State private var isShow: Bool = false
@State private var isAlert: Bool = false
var body: some View {
NavigationStack {
VStack {
NavigationLink(destination: SecondView()) {
Text("๋ค์์ผ๋ก ๊ฐ๋ณผ๊น์?")
}
Button(action: {
isShow.toggle()
}) {
Text("๋ชจ๋ฌ ๊บผ๋ด๊ธฐ")
}
.onAppear {
print("FirstView Appear")
}
.onDisappear {
print("FirstView Disappear")
}
}
.sheet(isPresented: $isShow, onDismiss: {
print("ModalSheet Dismiss")
}) {
VStack {
Text("๋? ๋ชจ๋ฌ")
Button(action: {
self.isAlert.toggle()
}) {
Text("์๋ ๋์ฐ๊ธฐ")
.onAppear {
print("Alert Appear")
}
.onDisappear {
print("Alert Disappear")
}
}
.alert("์๋
", isPresented: $isAlert) {
Button("ํ์ธ") {}
} message: {
Text("๋? ์๋")
}
}
.onAppear {
print("ModelSheet Appear")
}
.onDisappear {
print("ModelSheet Disappear")
}
}
}
}
}
๊ณผ์ฐ?
์ด๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์๊ฐํ๋ ๋๋ก ํธ์ถ๋๋ค!
UI hierarchy๊ฐ ๊ถ๊ธํด์ ์ถ๋ ฅํด๋ดค๋ค.
์ญ์ ์ด๋ฒ์๋ Controller๊ฐ ์กด์ฌํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Controller๊ฐ ์กด์ฌํ๋ ๋ทฐ๋ผ๊ณ ํ ๊น?
์ด๋ฌํ ๋ทฐ๋ค์ ๋ทฐ ์์ฒด์ Life cycle modifier๋ฅผ ๋ฌ์ง ๋ง๊ณ ,
๋ด๋ถ์ ์กด์ฌํ๋ ๋ทฐ์ modifier๋ฅผ ๋ฌ์์ผ
์ฐ๋ฆฌ๊ฐ ์๋ํ๋ ๋๋ก ์๋ํ๋ค.
์ง๋ ํฌ์คํ ์์๋ ScrollView ์์ฒด์ ๋ฌ์ง ์๊ณ , ๋ด๋ถ์ ์กด์ฌํ๋ LectureItemView์ ๋ฌ์์ค ๊ฒ์ฒ๋ผ ๋ง์ด๋ค.
๋ง์ฝ Life cycle์ด ์ ๋๋ก ๋์ํ์ง ์๋๋ค๋ฉด, Controller์ ๋ฌ๋ ค์๋ ํ์ธํด ๋ณผ ๊ฒ!