Swift中如何将缩放平移旋转后的图片状态原样传递到另一个ViewController
问题解决方案
问题根源
你遇到的变换后尺寸不对的问题有两个核心原因:
CGAffineTransform是相对于视图自身初始bounds、父视图坐标系的相对值,你在A控制器中处理手势时同时修改了center(平移)和transform(缩放、旋转)两类属性,仅传递transform自然无法还原完整状态。- 你当前代码中B控制器里声明的
fetchImageViewToTest和createCanvas方法中新建的image_View1是完全独立的两个视图,从A传过来的变换后视图根本没有被加到B的视图层级上,自然无法正确显示。
方案1:直接迁移已变换的视图(推荐,零误差)
直接把A控制器中已经完成所有变换的图片视图转移到B控制器中,不需要重新创建视图,完全复用原有状态,步骤如下:
修改ViewControllerB代码
删除createCanvas中新建image_View1的逻辑,改为接收外部传入的图片视图:
class ViewControllerB: UIViewController { // 接收A传过来的图片视图 var receivedImageView: UIImageView? // 容器视图和你原有逻辑保持一致 var containerView: UIView! override func viewDidLoad() { super.viewDidLoad() createCanvas() // 把传入的图片视图加到容器上 if let imageView = receivedImageView { // 先从原来的父视图移除 imageView.removeFromSuperview() containerView.addSubview(imageView) // 不需要加约束,原有frame、transform、center都已经是正确状态 } } func createCanvas() { containerView = { let viewView = UIView() viewView.translatesAutoresizingMaskIntoConstraints = false viewView.contentMode = .scaleAspectFit viewView.backgroundColor = .white viewView.clipsToBounds = true return viewView }() self.view.addSubview(containerView) // 原有约束逻辑保持不变 containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true containerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: 0).isActive = true containerView.heightAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1.0).isActive = true } }
修改ViewControllerA跳转逻辑
@IBAction func backBtnCanvas(_ sender: UIButton) { let VC = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") as! ViewControllerB // 直接传已经变换完成的imageView VC.receivedImageView = imageViewToTest let window = UIApplication.shared.windows.first window?.rootViewController = VC }
方案2:传递变换参数手动拼接
如果需要两个控制器各自维护独立的图片视图,可以在A中存储所有变换参数,传递到B后手动拼接变换:
- 首先在ViewControllerA中补充存储变换参数的属性,在手势回调中更新对应值:
// ViewControllerA新增属性 var currentScale: CGFloat = 1.0 var currentRotation: CGFloat = 0.0 var currentOffset: CGPoint = .zero
在pinchAction中更新currentScale,rotateAction中更新currentRotation,handlePanGesture中更新currentOffset。
2. 跳转时把图片、currentScale、currentRotation、currentOffset四个参数传递给ViewControllerB。
3. ViewControllerB中拿到参数后按平移→旋转→缩放的顺序拼接transform:
let transform = CGAffineTransform.identity .translatedBy(x: currentOffset.x, y: currentOffset.y) .rotated(by: currentRotation) .scaledBy(x: currentScale, y: currentScale) imageView.transform = transform // 同时把imageView的center设置为和A中一致的值 imageView.center = CGPoint(x: positionX, y: positionY)
注意事项
- 两个控制器的容器视图尺寸必须完全一致,否则相对位置会出现偏差,你当前代码中容器都是宽等于屏幕宽、高等于宽,符合要求。
- 不要同时修改视图的
center和transform的平移属性,统一用一种方式处理平移即可,避免状态冲突。
内容的提问来源于stack exchange,提问作者iosDevSan
相关产品推荐
相关产品推荐

