43

The .animation() modifier has been deprecated in iOS 15, but I'm not sure I understand how Xcode's suggested equivalent, animation(_:value:), works.

.animation(.easeInOut(duration: 2)) // ⚠️'animation' was deprecated in iOS 15.0: Use withAnimation or animation(_:value:) instead.

How would I change my code to get rid of the warning?

Sam
  • 2,152
  • 6
  • 31
  • 44

6 Answers6

62

You need tell Xcode what exactly should be animated! With given a variable that conform to Equatable protocol. That could be State or Binding or any other wrapper that allow you to update the value of it.

Example:

struct ContentView: View {
    
    @State private var offset: CGFloat = 200.0
    
    var body: some View {
        
        Image(systemName: "ant")
            .font(Font.system(size: 100.0))
            .offset(y: offset)
            .shadow(radius: 10.0)
            .onTapGesture { offset -= 100.0 }
            .animation(Animation.easeInOut(duration: 1.0), value: offset)
        
    }
}

Result:

enter image description here

ios coder
  • 1
  • 4
  • 31
  • 91
  • I'm not following this. Can you provide a code example? Thanks. – Sam Oct 05 '21 at 00:25
  • Yes, I update a sample for you, 1 min – ios coder Oct 05 '21 at 00:26
  • Ok. I still don't exactly understand why this is different/better (can you explain?), but I got it to work. Thanks. – Sam Oct 05 '21 at 00:41
  • 6
    I believe Apple just took right decision to deprecated the `.animation(animation:)` because when you and me use that modifier SwiftUI would apply animation to anything that change in value! Which might not our goal! It could gave unwanted or wired animation even! or extra load to CPU! with this new method we are explicitly saying what we need to get animated! also has a down side! Now we should use so many this kind of modifiers to cover all values should be get animated! – ios coder Oct 05 '21 at 00:48
  • @IgorMuzyka: Please make a question, and I can answer it for you. You can share your question link here. thanks – ios coder Apr 13 '22 at 21:02
  • @swiftPunk https://stackoverflow.com/questions/71864687/animation-was-deprecated-in-ios-15-0-use-withanimation-or-animation-value – Igor Muzyka Apr 13 '22 at 23:04
  • It's best to think of the value argument as the trigger. In this case, when the offset value changes, the animation is started – Tommy Herbert Feb 03 '23 at 19:53
17

You can also use the animation by using a boolean as the value.

Example Below: When you tap the CardView(), it will toggle show which in turn will animate the offset both ways.

@State var show = false

CardView()
 .offset(x: 0, y: show ? -100 : -10)
 .animation(.easeInOut(duration: 1.0), value: show)
 .onTapGesture {
   show.toggle()
 }
STerrier
  • 3,755
  • 1
  • 16
  • 41
14

UUID


extension View {
    func withoutAnimation() -> some View {
        self.animation(nil, value: UUID())
    }
}


demo

/*

.animation(
  Animation
    .easeInOut(duration: 1.5)
    .repeatForever(autoreverses: true)
)

*/

// ⚠️ 'animation' was deprecated in iOS 15.0,
// Use withAnimation or animation(_:value:) instead.


// value: UUID ✅
.animation(
  Animation
    .easeInOut(duration: 1.5)
    .repeatForever(autoreverses: true), 
  value: UUID()
)


refs

https://developer.apple.com/forums/thread/688947

xgqfrms
  • 10,077
  • 1
  • 69
  • 68
3

Another approach would be to embed ontapGesture in a withAnimation

struct SwiftUWithAnimation: View {
@State private var offset: CGFloat = .zero

var body: some View {
    
    Circle()
        .frame(width: 100, height: 100, alignment: .center)
        .offset(x: 0, y: offset)
        .onTapGesture {
            withAnimation(.default) {
                offset += 100.0
         }
      }
   }
}
L. Puzer
  • 55
  • 5
1

.animation now takes a second argument called value.

https://developer.apple.com/documentation/swiftui/view/animation(_:value:)

iPaat
  • 792
  • 4
  • 16
  • How could nil conform to Equatable? can you conform? – ios coder Oct 05 '21 at 00:21
  • Weirdly, the warning disappears, but now there's an error on the `.rotation3DEffect()` that's above it: "Generic parameter 'V' could not be inferred" – Sam Oct 05 '21 at 00:22
  • Well, nil is not working then. See documentation for further help: https://developer.apple.com/documentation/swiftui/view/animation(_:value:) – iPaat Oct 05 '21 at 00:27
0

for a continuous animation update the value with a timer

private let timer = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
@State private var start = UnitPoint(x: 0, y: 0)
@State private var end = UnitPoint(x: 0.5, y: 0.5)
@State private var val = 1
                
var body: some View {
   LinearGradient(gradient: Gradient(colors: [.pink, .orange]), startPoint: start, endPoint: end)
      .animation(
         Animation.easeInOut(duration: 1).repeatForever(autoreverses: true).speed(0.5),
         value: val
      )
      .onReceive(timer, perform: { _ in
         val += 1
         self.start = UnitPoint(x: 0.5, y: 0)
         self.end = UnitPoint(x: 0, y: 0.5)
      })
}
Salvador
  • 61
  • 1
  • 8