如何在Swift中进行全屏截图?

81

我找到了这段代码

func screenShotMethod() {
    //Create the UIImage
    UIGraphicsBeginImageContext(view.frame.size)
    view.layer.renderInContext(UIGraphicsGetCurrentContext())
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    //Save it to the camera roll
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}

我需要做什么才能将其他元素(例如导航栏)也显示在截图中?


你知道如何在Objective-C中进行全屏截图吗? - Mohit
是的,但我不知道相关的代码。 - Pietro La Spada
CALayer *layer = [[UIApplication sharedApplication] keyWindow].layer; CGFloat scale = [UIScreen mainScreen].scale; UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, scale); [layer renderInContext:UIGraphicsGetCurrentContext()]; image = UIGraphicsGetImageFromCurrentImageContext();这段代码是用于在Objective-C中截取全屏截图的。如果要将其转换为Swift,请使用以下代码: - Mohit
谢谢,但是没有状态栏。 - Pietro La Spada
21个回答

2

为UIWindow添加Swift 3扩展

public extension UIWindow {

  func capture() -> UIImage? {

    UIGraphicsBeginImageContextWithOptions(self.frame.size, self.isOpaque, UIScreen.main.scale)
    self.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image

  }
}]

2
这是我在Swift 4中的做法。最初的回答:
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);                 
layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

现在屏幕截图将会是UIImage类型。最初的回答已经涉及到此问题。

1

1
  // Full Screen Shot function. Hope this will work well in swift.
  func screenShot() -> UIImage {                                                    
    UIGraphicsBeginImageContext(CGSizeMake(frame.size.width, frame.size.height))
    var context:CGContextRef  = UIGraphicsGetCurrentContext()
    self.view?.drawViewHierarchyInRect(frame, afterScreenUpdates: true)
    var screenShot = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext();  
    return screenShot
  }

1

这段代码是最新版本 - 100% 可用

func getScreenshoot() -> UIImage {
    var window: UIWindow? = UIApplication.shared.keyWindow
    window = UIApplication.shared.windows[0] as? UIWindow
    UIGraphicsBeginImageContextWithOptions(window!.frame.size, window!.isOpaque, 0.0)
    window!.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image!;
}

1
尝试这个函数() 它可以正常工作:

extension View {
    func snapshot() -> UIImage {
        let size = CGSizeMake(UIScreen.main.bounds.width,UIScreen.main.bounds.height)
        let controller = UIHostingController(rootView: self.ignoresSafeArea())
        let view = controller.view
        view?.bounds = CGRect(origin: .zero, size: size)
        let renderer = UIGraphicsImageRenderer(size: size)
        return renderer.image { _ in
            view?.drawHierarchy(in:CGRect(origin: .zero, size: size), afterScreenUpdates: true)
        }
    }
}

0

我的版本还可以捕获键盘。Swift 4.2

extension UIApplication {

    var screenshot: UIImage? {
        UIGraphicsBeginImageContextWithOptions(UIScreen.main.bounds.size, false, 0)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        for window in windows {
            window.layer.render(in: context)
        }
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

}

但它无法捕获状态栏,有什么建议吗? - Pavan
1
@Pavan 我不知道这件事,因为在我的当前应用程序中没有状态栏。 - Alexander Khitev
我正在尝试在示例代码上进行操作,类似于通过电源+主页按钮模拟屏幕截图,但是这段代码无法捕获状态栏。 - Pavan

0

iOS 16 之后,您可以使用 ImageRenderer 从 SwiftUI 视图中导出位图图像数据。

请记住,您必须在主线程上调用它。我在这里使用了 MainActor。但是,在此示例中,因为它总是在主线程上触发按钮操作,因此 MainActor 是不必要的。

struct ContentView: View {
    
    @State private var renderedImage = Image(systemName: "photo.artframe")
    @Environment(\.displayScale) var displayScale

    
    var body: some View {
        VStack(spacing: 30) {
            renderedImage
                .frame(width: 300, height: 300)
                .background(.gray)
            
            Button("Render SampleView") {
                let randomNumber = Int.random(in: 0...100)
                let renderer = ImageRenderer(content: createSampleView(number: randomNumber))
                
                /// The default value of scale property is 1.0
                renderer.scale = displayScale
                
                if let uiImage = renderer.uiImage {
                    renderedImage = Image(uiImage: uiImage)
                }
            }
        }
    }
    
    @MainActor func createSampleView(number: Int) -> some View {
        Text("Random Number: \(number)")
            .font(.title)
            .foregroundColor(.white)
            .padding()
            .background(.blue)
    }
}

0

由于自iOS 13起,UIApplication.shared.keyWindow已被弃用,因此这里提供基于@Imanou Petit的答案的Swift 5 Xcode 14更新解决方案。

extension UIWindow {

static let keyWindow: UIWindow? = {
    return UIApplication.shared.delegate?.window ?? nil
}()

@discardableResult
static func takeScreenshot(shouldSave: Bool) -> UIImage? {
    var screenshotImage: UIImage?
    guard let layer = UIWindow.keyWindow?.layer else {
        return nil
    }
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
    guard let context = UIGraphicsGetCurrentContext() else {
        return nil
    }
    layer.render(in:context)
    screenshotImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    if let image = screenshotImage, shouldSave {
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
    return screenshotImage
  }
}

使用方法:

let myScreenshotImage = UIWindow.takeScreenshot(shouldSave: false)

0
视图快照视图(afterScreenUpdates: true)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接