티스토리 뷰
SwiftUI에서 animation(_:value:)을 사용해 애니메이션을 구현했는데 동작을 하지 않았습니다.
한동안 헤메다가 생명주기 때문이란 걸 알았습니다.
이번 글에서는 animation(_:value:)를 정확히 이해하고 왜 애니메이션이 동작 안 했는지 살펴보겠습니다.
값(Value)이 바뀔 때 에니메이션이 적용되는 메소드
기존에는 animation(_ animation:)을 사용해서 애니메이션을 설정해주었습니다. 하지만 이 메소드는 iOS 15.0 부터는 사용하지 않고 대신에 animation(_:value:)를 사용하게 됩니다.
공식문서의 animation(_:value:)를 살펴보겠습니다.
animation의 경우 옵셔널 값을 받으며 nil 값일 때는 동작하지 않습니다.
value에는 넣어준 값이 변하면 애니메이션이 동작하게 됩니다.
struct ContentView: View {
@State var isPresented: Bool = false
var body: some View {
VStack {
MyImage()
.animation(.easeInOut, value: isPresented)
}
}
}
간단한 예시 코드입니다. MyImage라는 View에 애니메이션을 적용했습니다.
.easeInOut으로 동작하게 되고 isPresented가 바뀔 때 애니메이션이 동작합니다.
실제 동작을 확인하기 위해 opacity와 버튼을 추가해주겠습니다.
struct ContentView: View {
@State var isPresented: Bool = false
var body: some View {
VStack {
MyImage()
.opacity(isPresented ? 1.0 : 0)
.animation(.easeIn, value: isPresented)
Spacer()
Button(
action: { isPresented.toggle() },
label: { Text("변해라 얍") }
)
.buttonStyle(.borderedProminent)
.padding(.top)
}
.padding()
}
}
struct MyImage: View {
var body: some View {
Image(systemName: "globe")
.resizable()
.scaledToFit()
.imageScale(.large)
.foregroundStyle(.tint)
}
}
버튼을 누르면 isPresneted 값이 바뀌고, opacity가 바뀌면서 애니메이션이 동작됩니다.
여기까지는 쉽게 사용이 가능합니다.
if문을 사용할 때
Opacity를 0으로 설정한다면 View가 화면과 메모리에 남아있기 때문에 if문을 사용하는게 나은 경우도 있습니다.
위 사진은 카카오 지하철 앱입니다. 앱 시작시 새로운 서비스에 대한 팝업이 뜨는데, x 버튼을 누르게 된다면 앱이 끝날 때까지 해당 View는 보여지지 않습니다. 이런 경우 Opacity를 0으로 설정해서 부모 View와 메모리에 남겨 놓기보다는 없애는게 좋다는 생각이 듭니다.
앞선 예시 코드를 if문으로 바꿔주겠습니다.
struct ContentView: View {
@State var isPresented: Bool = false
var body: some View {
VStack {
if isPresented {
MyImage()
.animation(.easeIn, value: isPresented)
}
// 위와 동일
}
}
}
이제 isPresented가 true일 때만 MyImage를 보여줍니다.
결과를 확인해보면..!
잉?
되긴 되는데 뭔가 어색한 느낌이 들지 않나요?
앞선 예시와 비교해보면 애니메이션이 적용되지 않은 걸 알 수 있습니다.
opacity 코드를 없애서 그런거 아니야???
// opacity
if isPresented {
MyImage()
.opacity(isPresented ? 1.0 : 0.0)
.animation(.easeIn, value: isPresented)
}
// transition 사용
if isPresented {
MyImage()
.transition(.opacity)
.animation(.easeIn, value: isPresented)
}
위 코드 예시 모두 똑같이 애니메이션이 동작하지 않습니다.
외않되????
바로 생명주기 때문입니다.
isPresented 값이 바뀌고 MyImage가 생성되고 animation의 value 값은 항상 true가 됩니다.
앞서서 value 값이 바뀌는 걸 확인하고 애니메이션이 동작된다고 했는데 항상 true가 들어가기 때문에 생성되고 나서 값이 변하지 않습니다!
사라질 때도 마찬가지입니다.
value값이 바뀌기 전에 MyImage가 먼저 사라지기 때문에 애니메이션이 동작하지 않습니다.
해결책 : 다른 View로 감싸기
'그럼 if문 밖에 애니메이션을 사용하면 되지 않을까?' 하고 코드를 작성하면 아래와 같은 에러가 발생합니다.
if문의 코드 블럭 { } 이 View가 아니기 때문이죠.
Stack을 사용해서 감싸주면 쉽게 해결이 가능합니다. V, H, Z 중 상황에 맞게 사용하면 됩니다. 저는 VStack 사용했습니다.
var body: some View {
VStack {
VStack {
if isPresented {
MyImage()
.transition(.slide)
}
}
.animation(.easeIn, value: isPresented)
}
}
앞선 코드랑 다른 결과를 확인하기 위해 .transition(.slide)를 넣어주었습니다.
결과는...?
잘 동작하네요 👍
정리
예시 코드를 보면 생명주기가 명확합니다. 하지만 실제 프로젝트를 할 때는 View가 중첩돼있고 다른 파일에 있다보니 확인하는게 쉽지 않았던 거 같습니다.
withAnimation도 쓰고 여러 가지 해보며 해멨는데 결국엔 생명 주기가 답이였네요 😂
저와 같이 헤매는 분에게 도움이 되길 바라며....
끝
끝끝
끝끝끝
'SwiftUI > SwiftUI 공부' 카테고리의 다른 글
[SwiftUI] @Observable, @ObservationTracked, @ObservationIgnored 알아보기 (0) | 2023.10.16 |
---|---|
[SwiftUI] WKWebView 사용하기 (with 양방향 이벤트 전달) (1) | 2023.10.12 |
[SwiftUI] Color 사용하는 7가지 방법 (0) | 2022.09.12 |
- Total
- Today
- Yesterday
- 책후기
- vapor
- SwiftUI
- 코딩
- 개발
- 부스트캠프7기
- TODO
- 책리뷰
- Swift 디자인 패턴
- swiftUI 기초
- Swift DocC
- 부스트캠프iOS
- ios
- Swift 서버
- todo앱
- 코딩 테스트
- Combine
- 애플
- 책
- 프로그래머스
- 날씨어플
- Swift공식문서
- 필독서
- 앱개발
- Swift
- Swift문법
- 디자인 패턴
- 부스트캠프
- 코딩테스트
- UX
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |