How do I stop drawHierarchy from making my app flicker/flash?

265 Views Asked by At

I'm trying to convert my app's main view into PDF data using UIGraphicsPDFRenderer. The code sort of looks like this:

let pdfRenderer = UIGraphicsPDFRenderer()
let pdfData = pdfRenderer.pdfData { context in
  context.beginPage()
  view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
}

However, once I actually run this, it causes certain elements in my app to flicker every time drawHierarchy runs. this is what it looks like when run every second

I can change afterScreenUpdates to false to prevent this, but I need the latest update of the view in order for my capture to be accurate (I am hiding a subview from being captured)

I've also tried using view.layer.render(in: context), but the resulting capture isn't accurate (missing background colors).

Is there a way to avoid the flicker? I don't want to capture the password field or keyboard, but I definitely don't want them to be flickering.

Here is a very basic reproduction of the flashing behavior. If you have input in the password field and click "capture" the password field's input will flash.

1

There are 1 best solutions below

2
RTXGamer On

Edit:

Tried to capture it this way and it even captures the password field.

enter image description here

class Capture {
    static func capture() {
        
        let directory = FileManager.default.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first!
        let filePath =  directory.appendingPathComponent("Test.pdf")
        print(filePath)
        
        if let rootView = UIApplication.shared.windows.first?.rootViewController?.view {
            let pdfRenderer = UIGraphicsPDFRenderer(bounds: rootView.bounds)
            try! pdfRenderer.writePDF(to: filePath, withActions: { (context) in
                context.beginPage(withBounds: rootView.bounds, pageInfo: [:])
                rootView.layer.render(in: context.cgContext)
            })
        }
    }
}

1st Attempt:

It's going to flicker because it hides the password and keyword while capturing the screen:

enter image description here

Code used:

class Capture {
    static func capture() {
        
        let directory = FileManager.default.urls(for: FileManager.SearchPathDirectory.cachesDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first!
        let filePath =  directory.appendingPathComponent("Test.pdf")
        print(filePath)
        
        if let rootView = UIApplication.shared.windows.first?.rootViewController?.view {
            let pdfRenderer = UIGraphicsPDFRenderer(bounds: rootView.bounds)
            try! pdfRenderer.writePDF(to: filePath, withActions: { (context) in
                context.beginPage(withBounds: rootView.bounds, pageInfo: [:])
                rootView.drawHierarchy(in: rootView.bounds, afterScreenUpdates: true)
            })
        }
    }
}