iOS编程实现屏幕中间区域截图遇阻,求助排查代码问题
解决屏幕中间区域截取异常的问题
嘿,我看你现在遇到俩问题:一是savePhoto方法压根没进入执行流程,二是当前代码也没正确实现截取屏幕中间区域的需求。我来帮你一步步搞定:
一、先搞定方法没执行的问题
- 先检查按钮的IBAction关联是否正确:
- 打开Storyboard/XIB,选中你的按钮
- 打开右侧的Connections Inspector(箭头图标)
- 确认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
相关产品推荐
相关产品推荐

