swiftUI中旋转动画的性能不佳
我用swiftUI创建了一个指南针应用程序,一切正常,但是可以对指南针旋转的动画进行一些改进。我重新创建了一个只有指南针的项目,用代码来说明这一点。在这个版本中,不会报告任何性能问题,因为只有罗盘可以计算。但是在我的实际应用程序中,如果有更多的元素,性能就不是最优的 简易指南针应用程序代码: (出于技术原因,我必须将swiftUI中旋转动画的性能不佳,swift,performance,animation,swiftui,Swift,Performance,Animation,Swiftui,我用swiftUI创建了一个指南针应用程序,一切正常,但是可以对指南针旋转的动画进行一些改进。我重新创建了一个只有指南针的项目,用代码来说明这一点。在这个版本中,不会报告任何性能问题,因为只有罗盘可以计算。但是在我的实际应用程序中,如果有更多的元素,性能就不是最优的 简易指南针应用程序代码: (出于技术原因,我必须将UIKit与CGAffineTransform一起使用,以矩阵旋转为指南针旋转设置动画,以避免产生不必要的效果) 位置提供程序: import SwiftUI import UIKi
UIKit
与CGAffineTransform
一起使用,以矩阵旋转为指南针旋转设置动画,以避免产生不必要的效果)
位置提供程序:
import SwiftUI
import UIKit
import CoreLocation
import Combine
public class LocationProvider: NSObject, CLLocationManagerDelegate, ObservableObject {
private let locationManager: CLLocationManager
public let heading = PassthroughSubject<Double, Never>()
@Published var currentHeading: Double {
willSet {
heading.send(newValue)
}
}
public override init() {
currentHeading = 0
locationManager = CLLocationManager()
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingHeading()
}
public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
self.currentHeading = newHeading.magneticHeading
}
}
导入快捷界面
导入UIKit
导入核心定位
进口联合收割机
公共类LocationProvider:NSObject、CLLocationManagerDelegate、ObservableObject{
私人出租位置管理器:CLLocationManager
公共let heading=PassthroughSubject()
@当前标题:双{
意志{
标题.发送(newValue)
}
}
公共重写init(){
当前航向=0
locationManager=CLLocationManager()
super.init()
locationManager.delegate=self
locationManager.desiredAccuracy=KCallocationAccuracyBest
locationManager.startUpdatingHeading()
}
公共函数位置管理器(u管理器:CLLocationManager,didUpdateHeading新标题:CLHeading){
self.currentHeading=newHeading.magneticeHeading
}
}
罗盘视图:
import SwiftUI
import UIKit
import CoreLocation
public extension CGFloat {
var degreesToRadians: CGFloat { return self * .pi / 180 }
}
struct ContentView: View {
@ObservedObject var location: LocationProvider = LocationProvider()
private var windowWidth: CGFloat = UIScreen.main.bounds.width
@State private var heading: CGFloat = .zero
// Arrow view
struct ArrowView: UIViewRepresentable {
var angle: CGFloat
var width: CGFloat
var height: CGFloat
var container: UIView = UIView()
var imageView: UIImageView = UIImageView()
var imageName: String
func makeUIView(context: Context) -> some UIView {
// Container
container.frame = CGRect.init(
x: 0,
y: 0,
width: height < width ? height : width,
height: height < width ? height : width
)
container.isOpaque = true
// Image
imageView.image = UIImage(named: imageName)
imageView.frame = CGRect.init(
x: height < width ? 0 : 20,
y: height < width ? 0 : 20,
width: height < width ? height : width - 40,
height: height < width ? height : width - 40
)
imageView.isOpaque = true
container.addSubview(imageView)
return container
}
func updateUIView(_ uiView: UIViewType, context: Context) {
UIView.animate(withDuration: 0.2, delay: 0, options: UIView.AnimationOptions.curveEaseIn, animations: {
uiView.subviews[0].transform = CGAffineTransform(rotationAngle: -angle.degreesToRadians)
}, completion: nil)
// Mise à jour de l'image
let imageView = uiView.subviews.compactMap{ $0 as? UIImageView }
imageView[0].image = UIImage(named: imageName)
}
}
var body: some View {
VStack {
ArrowView(angle: self.heading, width: self.windowWidth - 20, height: self.windowWidth - 20, imageName: "arrow")
.frame(width: self.windowWidth, height: self.windowWidth, alignment: .center)
}
.onReceive(self.location.heading) { heading in
self.heading = CGFloat(heading)
}
}
}
导入快捷界面
导入UIKit
导入核心定位
公共扩展CGFloat{
变量度弧度:CGFloat{return self*.pi/180}
}
结构ContentView:View{
@ObservedObject变量位置:LocationProvider=LocationProvider()
私有变量windowWidth:CGFloat=UIScreen.main.bounds.width
@国家私有变量标题:CGFloat=.0
//箭头视图
结构ArrowView:UIViewRepresentable{
变量角度:CGFloat
变量宽度:CGFloat
变量高度:CGFloat
变量容器:UIView=UIView()
var-imageView:UIImageView=UIImageView()
var-imageName:String
func makeUIView(context:context)->一些UIView{
//容器
container.frame=CGRect.init(
x:0,,
y:0,
宽度:高度<宽度?高度:宽度,
高度:高度<宽度?高度:宽度
)
container.isOpaque=true
//形象
imageView.image=UIImage(名称:imageName)
imageView.frame=CGRect.init(
x:高度<宽度?0:20,
y:高度<宽度?0:20,
宽度:高度<宽度?高度:宽度-40,
高度:高度<宽度?高度:宽度-40
)
imageView.isOpaque=true
container.addSubview(imageView)
返回容器
}
func updateUIView(uiView:UIViewType,context:context){
UIView.animate(持续时间:0.2,延迟:0,选项:UIView.AnimationOptions.curveEaseIn,动画:{
uiView.subviews[0]。transform=CGAffineTransform(旋转角度:-角度.度数弧度)
},完成日期:无)
//你的形象如何
让imageView=uiView.subviews.compactMap{$0 as?UIImageView}
imageView[0]。image=UIImage(名称:imageName)
}
}
var body:一些观点{
VStack{
箭头视图(角度:self.heading,宽度:self.windowWidth-20,高度:self.windowWidth-20,图像名称:“箭头”)
.frame(宽度:self.windowWidth,高度:self.windowWidth,对齐:。中心)
}
.onReceive(self.location.heading){heading in
self.heading=CGFloat(heading)
}
}
}
我已经寻找了几种方法来解决这个问题,但我不确定最好的方法是什么
- 将代码分成一个子组件
- 使用SpriteKit制作指南针动画
- 我读到一种方法,可以在主线程之外执行一些任务