Rehan Ali Khan
Rehan Ali Khan

Reputation: 601

How to programmatically take a screenshot of an app in iOS with UIAlertController as the top controller?

extension UIViewController {
    static func takeScreenshot() -> UIImage? {
        guard let topController = UIApplication.getTopController() else { return nil }
        
        if let view = topController.view {
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
            
            defer { UIGraphicsEndImageContext() }
            
            if let context = UIGraphicsGetCurrentContext() {
                view.layer.render(in: context)
                let screenshot = UIGraphicsGetImageFromCurrentImageContext()
                return screenshot
            }
        }

        return nil
    }
}

This code works perfectly but the issue is when we have UIAlertController on top. I want to take a screenshot of the entire screen (not the status bar of course) but the controller as well as any alert controller that is presented on top. Right now the code is working fine if there is no alert controller on top.

Upvotes: 0

Views: 396

Answers (2)

Rehan Ali Khan
Rehan Ali Khan

Reputation: 601

This code did the job, for iOS 13 with iPad not supporting multiple scenes.

func takeScreenshot() -> UIImage? {
    
    guard let window = UIApplication.shared.windows.first else {
        return nil
    }
    
    let renderer = UIGraphicsImageRenderer(bounds: window.bounds)
    let image = renderer.image { _ in
        window.drawHierarchy(in: window.bounds, afterScreenUpdates: true)
    }
    
    return image
}

Upvotes: 0

Sandeep Singh
Sandeep Singh

Reputation: 266

Here's the function that might help

func captureScreenshot() -> UIImage? {
guard let keyWindowScene = UIApplication.shared.connectedScenes
    .filter({ $0.activationState == .foregroundActive })
    .first as? UIWindowScene else {
    return nil
}

guard let window = keyWindowScene.windows.first else {
    return nil
}

UIGraphicsBeginImageContextWithOptions(window.bounds.size, false, 0.0)
window.drawHierarchy(in: window.bounds, afterScreenUpdates: true)
let screenshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return screenshotImage

}

Upvotes: -1

Related Questions