You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何将缩放平移旋转后的图片状态原样传递到另一个ViewController

问题解决方案

问题根源

你遇到的变换后尺寸不对的问题有两个核心原因:

  1. CGAffineTransform是相对于视图自身初始bounds、父视图坐标系的相对值,你在A控制器中处理手势时同时修改了center(平移)和transform(缩放、旋转)两类属性,仅传递transform自然无法还原完整状态。
  2. 你当前代码中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后手动拼接变换:

  1. 首先在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:09:00