SwiftUI Shape concurrency warnings

How are SwiftUI Shapes supposed to work with Swift 6?

Shape conforms to View which uses @MainActor but the path function and animatableData are both nonisolated. How can they access animatable properties that have to be a var on the main actor?

Below is a simple Shape that will show these warnings:

struct SimpleShape: Shape {
    var width: Double
    
    var animatableData: Double {
        get { width }
        set { width = newValue }
    }
    
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let width = self.width
        path.addRect(.init(origin: rect.origin, size: .init(width: width, height: rect.height)))
        return path
    }
}
Answered by DTS Engineer in 790883022

@RyanLintott Thanks for flagging that. Could you please file a bug report and post the FB number here once you do. Please be sure to test on future beta releases as well.

I have a workaround, but I'm not 100% sure I understand why the Shape properties are nonisolated so I'm not sure if this actually safe or not.

struct SimpleShape: Shape {
    var width: Double

    nonisolated var animatableData: Double {
        get { MainActor.assumeIsolated { width } }
        set { MainActor.assumeIsolated { width = newValue } }
    }

    func path(in rect: CGRect) -> Path {
        return Path()
    }
}

@RyanLintott Thanks for flagging that. Could you please file a bug report and post the FB number here once you do. Please be sure to test on future beta releases as well.

Feedback filed: FB13864563

It seems I can't assumeIsolated. SwiftUI.AsyncRenderer does something with animatableData.

I'll need another workaround or fix for this issue.

The same issue appears when using animatableData with GeometryEffect:

struct ShakeEffect: GeometryEffect {

var position: CGFloat
var animatableData: CGFloat {
    get { position }
    set { position = newValue }
}

init(shakes: Int) {
    position = CGFloat(shakes)
}


func effectValue(size: CGSize) -> ProjectionTransform {
    return ProjectionTransform(
         CGAffineTransform(translationX: -30 * sin(position * 2 * .pi), 
               y: 0))
}

}

SwiftUI Shape concurrency warnings
 
 
Q