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

iOS编程实现屏幕中间区域截图遇阻,求助排查代码问题

解决屏幕中间区域截取异常的问题

嘿,我看你现在遇到俩问题:一是savePhoto方法压根没进入执行流程,二是当前代码也没正确实现截取屏幕中间区域的需求。我来帮你一步步搞定:

一、先搞定方法没执行的问题

  • 先检查按钮的IBAction关联是否正确:
    1. 打开Storyboard/XIB,选中你的按钮
    2. 打开右侧的Connections Inspector(箭头图标)
    3. 确认Touch Up Inside事件已经连接到ViewController的savePhoto方法
  • 也可以在savePhoto方法第一行加个print("savePhoto被触发啦"),运行后点按钮看控制台有没有输出,确认是不是真的没执行

二、正确实现屏幕中间区域的截取

你当前的代码是把整个view渲染到1024x1024的上下文里,这可不是截取中间区域的正确姿势。下面给你两种靠谱的实现方式:

方式1:先截全屏,再裁剪中间区域

这种方式逻辑清晰,容易调试:

@IBAction func savePhoto(_ sender: UIButton) {
    print("savePhoto被触发啦")
    
    // 1. 获取当前keyWindow的全屏截图
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
          let window = windowScene.windows.first(where: { $0.isKeyWindow }) else {
        print("拿不到keyWindow,没法截图")
        return
    }
    let fullScreenImage = window.snapshotView(afterScreenUpdates: true)?.asImage()
    
    // 2. 计算要截取的中间区域的frame
    let targetSize = CGSize(width: 1024, height: 1024)
    let cropOriginX = (window.bounds.width - targetSize.width) / 2
    let cropOriginY = (window.bounds.height - targetSize.height) / 2
    let cropRect = CGRect(x: cropOriginX, y: cropOriginY, width: targetSize.width, height: targetSize.height)
    
    // 3. 裁剪出中间区域的图片
    if let fullImage = fullScreenImage, let croppedCGImage = fullImage.cgImage?.cropping(to: cropRect) {
        let finalImage = UIImage(cgImage: croppedCGImage, scale: UIScreen.main.scale, orientation: fullImage.imageOrientation)
        // 把图片保存到相册
        UIImageWriteToSavedPhotosAlbum(finalImage, self, #selector(imageSavedCallback(_:error:context:)), nil)
    }
}

// 辅助方法:把UIView转成UIImage
extension UIView {
    func asImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { ctx in
            layer.render(in: ctx.cgContext)
        }
    }
}

// 保存相册的回调方法
@objc func imageSavedCallback(_ image: UIImage, error: Error?, context: UnsafeRawPointer) {
    if let err = error {
        print("保存失败:\(err.localizedDescription)")
    } else {
        print("图片成功存到相册啦!")
    }
}

方式2:直接渲染中间区域到上下文(更高效)

如果不想先截全屏,可以直接只渲染view的中间部分,减少内存占用:

@IBAction func savePhoto(_ sender: UIButton) {
    print("savePhoto被触发啦")
    
    let targetSize = CGSize(width: 1024, height: 1024)
    let viewBounds = view.bounds
    
    // 计算中间区域的原点
    let offsetX = (viewBounds.width - targetSize.width) / 2
    let offsetY = (viewBounds.height - targetSize.height) / 2
    
    // 创建对应尺寸的上下文,平移后只渲染中间区域
    UIGraphicsBeginImageContextWithOptions(targetSize, false, UIScreen.main.scale)
    if let ctx = UIGraphicsGetCurrentContext() {
        // 平移上下文,让中间区域对应到上下文的原点
        ctx.translateBy(x: -offsetX, y: -offsetY)
        view.layer.render(in: ctx)
    }
    let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    if let finalImage = croppedImage {
        UIImageWriteToSavedPhotosAlbum(finalImage, self, #selector(imageSavedCallback(_:error:context:)), nil)
    }
}

// 同样需要上面的imageSavedCallback方法

几个重要提醒

  • iOS 13+ 建议用connectedScenes获取keyWindow,因为UIApplication.shared.windows已经被废弃了
  • 别忘了在Info.plist里添加NSPhotoLibraryAddUsageDescription,说明你的app为什么需要访问相册,否则保存会失败

内容的提问来源于stack exchange,提问作者curiousnoob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:19:51