Posts

Post marked as solved
4 Replies
Edit: I've since figured it out. Here's the correct solution, as far as I know. It compiles without errors, runs without problems, and gives the correct result. So, unless someone sees a problem I'm not seeing, I'm now happy to consider this question resolved. The problem with the previous implementation is on line 23: by creating a local mutable copy of self and operating on *that*, self itself doesn't get changed. import Foundation import CoreGraphics import Accelerate extension CGPoint: AccelerateMutableBuffer { 		public typealias Element = Double 		public var count: Int { 2 } 		public func withUnsafeBufferPointer<R>(_ body: (UnsafeBufferPointer<Double>) throws -> R) rethrows -> R { 				try Swift.withUnsafeBytes(of: self) { urbp in 						try body(urbp.bindMemory(to: Double.self)) 				} 		} 		public mutating func withUnsafeMutableBufferPointer <R> ( 				_ body: (inout UnsafeMutableBufferPointer<Double>) throws -> R 		) rethrows -> R { 				try Swift.withUnsafeMutableBytes(of: &self) { umrbp in 						var umbp = umrbp.bindMemory(to: Double.self) 						return try body(&umbp) 				} 		} } let p1 = CGPoint(x: 1.5, y: 3.5) let p2 = CGPoint(x: 0.5, y: 2.5) var p: CGPoint = .zero vDSP.add(p1, p2, result: &p) p // (x: 2, y: 6)	✅
Post marked as solved
4 Replies
I understand the error message now. The Element type of the type conforming to Accelerate[Mutable]Buffer must be a Double. I can live with that since CGFloat is a Double on a 64-bit platform. Still, vDSP is not returning the correct result. Again, what am I doing incorrectly? Many thanks. import Foundation import CoreGraphics import Accelerate extension CGPoint: AccelerateMutableBuffer {     public typealias Element = Double     public var count: Int { 2 }     public func withUnsafeBufferPointer <R> (         _ body: (UnsafeBufferPointer<Element>) throws -> R     ) rethrows -> R {         var varself = self         let ubp = withUnsafeBytes(of: &varself) { urbp in             urbp.bindMemory(to: Element.self)         }         return try body(ubp)     }     public mutating func withUnsafeMutableBufferPointer <R> (         _ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R     ) rethrows -> R {         var varself = self         var umbp = withUnsafeMutableBytes(of: &varself) { umrbp in             umrbp.bindMemory(to: Element.self)         }         return try body(&umbp)     } } let p1 = CGPoint(x: 1.5, y: 3.5) let p2 = CGPoint(x: 0.5, y: 2.5) var p: CGPoint = .zero vDSP.add(p1, p2, result: &p) p	 //	result is (0.0, 0.0), not the expected (2.0, 6.0)
Post marked as solved
4 Replies
Doh! 🤦🏻‍♂️ I accidentally clicked on that checkmark button and now I can't uncheck it. This question is not yet resolved!
Post marked as solved
4 Replies
Follow-up... After some more digging, and reading, and trial and error, I managed to get the implementation below, which I think is correct. However, now Xcode gives me a vDSP error that I don't understand, since CGPoint is now conforming to the types that vDSP expects its arguments and return values to have. What am I doing incorrectly? (The code below is in a Playground) import Foundation import CoreGraphics import Accelerate extension CGPoint: AccelerateMutableBuffer {     public var count: Int { 2 }     public func withUnsafeBufferPointer<R>( _ body: (UnsafeBufferPointer<CGFloat>) throws -> R ) rethrows -> R {         var varself = self         let ubp = withUnsafeBytes(of: &varself) { urbp in             urbp.bindMemory(to: CGFloat.self)         }         return try body(ubp)     }     public mutating func withUnsafeMutableBufferPointer<R>( _ body: (inout UnsafeMutableBufferPointer<CGFloat>) throws -> R ) rethrows -> R {         var varself = self         var ubp = withUnsafeMutableBytes(of: &varself) { urbp in             urbp.bindMemory(to: CGFloat.self)         }         return try body(&ubp)     } } let p1 = CGPoint(x: 1.5, y: -3.5) let p2 = CGPoint(x: -0.5, y: 2.5) var p: CGPoint = .zero vDSP.add(p1, p2, result: &p) // Error: "No exact matches in call to static method 'add(_:_:result:)'" p
Post marked as solved
67 Replies
Post not yet marked as solved
3 Replies
I nearly got a working implementation (well, in theory) but I got stuck because of a private API.import SwiftUI struct ContentView: View { var body: some View { CircleView() .animating(\.s, // QQQ Not sure why the generic parameter Value could not be inferred from: 0.2, to: 0.8, startingAt: 0.3, animation: .basic(duration: 0.8, curve: .easeInEaseOut), isActive: true) } } struct CircleView: View { @AutoAnimated private var s: CGFloat var body: some View { Circle() .fill(Color.red) .scaleEffect(s) } } #if DEBUG struct ContentView_Previews : PreviewProvider { static var previews: some View { ContentView() } } #endif // =========================================== // // QQQ There should be an extension to ViewModifier that does work // nearly identical to that of the extension to View below, so that // we can call '.animating(...)' on the result of another view modifier. public extension ViewModifier {} // ==================== // public extension View { func animating<Value: BinaryFloatingPoint>(_ propertyKeyPath: WritableKeyPath<Body, Value>, from fromValue: Value = 0, to toValue: Value = 1, startingAt startValue: Value, animation: Animation = .default, isActive: Bool = true) -> some View where Body == AutoAnimationViewModifier<Value>.Body { return AutoAnimationViewModifier<Value>() .animating(propertyKeyPath, from: fromValue, to: toValue, startingAt: startValue, animation: animation, isActive: isActive) .body(content: self.body) // QQQ Don't know how to fix the type mismatch here, // since it involves a type private to SwiftUI } } // ==================== // public struct AutoAnimationViewModifier<Value: BinaryFloatingPoint>: ViewModifier { public init() {} public func animating(_ propertyKeyPath: WritableKeyPath<Body, Value>, from fromValue: Value = 0, to toValue: Value = 1, startingAt startValue: Value = 0, animation: Animation = .default, isActive: Bool = true) -> AutoAnimationViewModifier { .init(propertyKeyPath, from: fromValue, to: toValue, startingAt: startValue, animation: animation, isActive: isActive) } public func body(content: Content) -> some View { content // QQQ Not sure how to apply the animation since the whole point // is not to have to explicitly trigger model changes } private var animatedPropertyKeyPath: WritableKeyPath<Body, Value>! private var from: Value = 0 private var to: Value = 1 private var startingAt: Value = 0 private var animation: Animation = .default private var isActive: Bool = true private init(_ propertyKeyPath: WritableKeyPath<Body, Value>! = nil, from fromValue: Value = 0, to toValue: Value = 1, startingAt startValue: Value, animation: Animation = .default, isActive: Bool = true) { self.animatedPropertyKeyPath = propertyKeyPath self.from = fromValue self.to = toValue let low = min(fromValue, toValue) let high = max(fromValue, toValue) self.startingAt = min(max(low, startingAt), high) self.animation = animation self.isActive = isActive } } // ==================== // @propertyWrapper public struct AutoAnimated<Value: BinaryFloatingPoint> { @State private var storage: Value = 0 public init() {} public var value: Value { storage } }
Post not yet marked as solved
3 Replies
For reference, I’ve logged a suggestion with Apple’s issue tracker. The issue number is FB6145347.
Post not yet marked as solved
3 Replies
Upon further reflection, I think the idea I suggested above (assuming it makes sense and that there’s no simpler way to do it already) could be enhanced by adding an ‘isActive’ boolean to the view modifier function ‘.animating(...)’ so that we can programmatically start or stop the animation.Moreover, since the animation is entirely under SwiftUI’s control, maybe those exposed properties should be marked with a property wrapper that gives SwiftUI read-write access but gives the view that exposes them read-only access.So, something like the following:struct SomeView { @AutoAnimated private var x: CGFloat // the compiler ensures that x is read-only to us but read-write to SwiftUI // .... } struct EnclosingView { @State private var xAnimActive = true // this view can set and change this value to control the animation life cycle SomeView() .animating(\.x, from: /* some value */, to: /* some value */, startingAt: /* some value */, animation: /* some animation here */, active: xAnimActive) }