적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

Swift iOS 앱 개발/Swift 튜토리얼

[Stanford iOS] Lecture 6. Animation

hongssup_ 2021. 4. 9. 10:12
반응형

SwiftUI Lecture 6.

  • Property Observers - 'Watching' a var and reating to changes
  • @State
    - State that is entirely localized inside a View Only used for temporary state like presentations of alerts or editing things or animation
  • Animation
    - Implicit vs. Explicit Animation
    - Animating Views (via their ViewModifiers which can implement the Animatable protocol)
    - Transitions (animating the appearance/disappearance of Views by specifying ViewModifiers)
    - Animating Shapes (via the Animatable protocol)

 

Property Observers

: essentially a way to “watch” a var and execute code when it changes

var isFaceUp: Bool {
    willSet {
        if newValue {
            startUsingBonusTime()
        } else {
            stopUsingBonusTime()
        }
    }
}

computed var랑 헷갈리는 경우가 있는데, 여기서 property observer를 가진 var isFaceUp은 stored in memory. 그래서 아무상관 x

property observer 'willSet' - just watching for when isFaceUp is gonna be set

in willSet, newValue is a special variable (the value it's going to get set to)

There’s also a didSet (inside that one, oldValue is what the value used to be).

isFaceUp 값이 false로 바뀌려고 하면 그걸 감지하고 stop using bonus time

 

@State

Your View is Read Only 

모든 View 구조체는 읽기전용이다. 

(View 생성할 때 초기화되는 변수 빼고는) SwiftUI가 뷰를 유지하기 위해 사용하는 변수를 살펴보면 다 let으로 선언되어 있음. 

변수들이 immutable 하면 좋은점은 이상한 곳에서 맘대로 막 바꿀 수 없다는 거

Why?

함수형 프로그래밍의 장점? 중 하나는 it's very clear about mutability. when can this be changed. 

mutable 하건 immutable하건 바뀌면 바뀌었다고 알 수 있기 때문에 property observer를 사용할 수 있다.

e.g., it makes it reliable and provable for it to manage changes and efficiently redraw things

View는 Model의 state를 받아와서 그리는 역할을 하기 때문에 자신의 state가 따로 필요하지 않다.

이처럼 View는 "stateless" 이기 때문에 읽기 전용이다. 대부분... 

When Views need State?  

모든 영구적인 State는 Model에서 관리를 하지만, 드물게 '일시적인' 상황에서는 View에도 State가 필요한 경우가 있다. 

예를들어, editing mode에서는 변경사항들이 Model에 반영되기 전에 일시적으로 Intent로 넘겨줄 변경사항들을 모아둔다.

Animation이 잠시 실행될 때 같은 temporary data들을 일시적으로 저장해야하는 상황에서,

to create storage in our read-only Views,

you must mark any vars used for this temporary state(storage) with @State

@State private var somethingTemporary: SomeType // this can be of any type

 @State라는 이 property wrapper는 View에서 사용하는 temporary storage이기 때문에 외부에서 볼 게 아니므로 private.

중요한건, changes to this @State var will cause your View to redraw if necessary

 

Animation

: UI change that has already happened(very recently) over a period of time. 

애니메이션을 실행하는 두가지 방법

- Implicit Animation

: Automatic animation. All ViewModifier arguments will always be animated. 잘 사용 안함.   

by using the view modifier .animation(Animation)

the changes are animated with the duration and "curve" you specify

Simply add a .animation(Animation) view modifier to the View you want to auto-animate

Text(“👻”)
    .opacity(scary ? 1 : 0)
    .rotationEffect(Angle.degrees(upsideDown ? 180 : 0))
    .animation(Animation.easeInOut)

주의할 점) ZStack 같은 컨테이너에 애니메이션을 적용하면, 컨테이너 내부의 모든 뷰들에 각각 애니메이션을 적용해버리기 때문에  

일반적으로 컨테이너 뷰가 아니라 독립적으로 작동하는  뷰에 사용한다. 

- Explicit Animation

by wrapping withAnimation(Animation) { } around code that might change things.

: {} 안의 사항들 동시에 한꺼번에 애니메이션 실행

withAnimation(.linear(duration: 2)) {
 // do something that will cause ViewModifier/Shape arguments to change somewhere
}

SwiftUI에서 드물게 사용되는 imperative programming

주의할 점) explicit animations do not override an implicit animation. 동시에 적용됐을때 implicit animations always win.

- Animation Duration

- Animation Curve

: 애니메이션을 어떤 속도로 작동시킬지 컨트롤해줌. 

  .linear : consistent rate throughout

  .easeInOut 

  .spring (= soft landing) : bounce at the end of the animation

- Transitions

Transitions specify how to animate the arrival/departure of Views 

a transition is only a pair of ViewModifiers : before / after modification of the View

built in transitions 예) .opacity(디폴트) / .scale / .identity

주의할 점) Transitions do not work with implicit animations, only explicit animations. 

All the transition API is 'type erased'

we use the struct AnyTransition

.onAppear : executes when a View appears on screen

 

 

Memorize Demo

  • Match Somersault
    Let’s have our emoji celebrate when there’s a match!
  • Card Rearrangement
    This is just changing the .position modifier on Views. Automatically animated if an animation is in progress.
  • Card Flipping
    Cardify can handle this since it is a ViewModifier.
    It will sync up the 3D rotation animation and the face-up-ness of the card.
  • Card Disappearing on Match
    This is a “transition” animation.
  • Bonus Scoring Pie Animation
    Make our Pie slice animate.

implicit animation

localized string 

wecan turn a viewModifier into an Animatable modifier by changing the protocol to AnimatableModifier

애니메이션은 지나간 자취?(did happen) 를 보여주는건데 앵글을 0->360으로 변화시키면 360이 되기 전에 그 중간 과정은 어떻게 애니메이션으로 보여주나? 

Model에서는 이러한 중간? 변화를 바로바로 가져올수는 없다. 

그렇기 때문에 View에 직접 temporary var를 만들어, 애니메이션이 실행되는 동안 변하는 state를 따로 저장해주어야 한다. 그런 다음 Model에 sync up 해주기. 

.onAppear { } 은 실행된다. anytime this View appears on screen. 그렇게 해서 늘 Model과 sync할 수 있도록  

 

 

참고 : Lecture 6

728x90
반응형