-1

This is the screenshot of the code. The view content includes UIView and WKWebView. The part of UIView is normal, but the part of WKWebView shows a blank screen. This was not a problem before iOS 26, but it occurred after upgrading to iOS 26. Who can help me? enter image description here

I attempted to change the screenshot view to "keywindow", but it didn't work.

1
  • 1
    Please copy /paste your code in the question so people can reproduce your problem. Commented Sep 5 at 7:29

2 Answers 2

3

Using the -(BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates API allows for the extraction of multiple levels of content within the view. This solved my problem.

Sign up to request clarification or add additional context in comments.

Comments

1

Capturing WKWebview is tricky with your view's layer, as WebKit lives in a standalone process. Luckily, there is a dedicated API that captures screenshot from WKWebview

takeSnapshotWithConfiguration:completionHandler:

In OC, you should use it like this:

 - (void)captureWebViewSnapshot:(WKWebView *)webView {
            if (!webView) { return; }

            // Optional: guard against capturing while loading
            if (webView.isLoading) {
                // Show an alert/toast as needed and return
                return;
            }

            WKSnapshotConfiguration *config = [[WKSnapshotConfiguration alloc] init];
            config.rect = webView.bounds; // viewport coordinates

            [webView takeSnapshotWithConfiguration:config
                                 completionHandler:^(UIImage * _Nullable image, NSError * _Nullable error) {
                if (error) {
                    // Handle error (e.g., show alert with error.localizedDescription)
                    return;
                }
                if (!image) {
                    // Handle empty image
                    return;
                }

                // TODO: SAVE IMAGE HERE.
            }];
        }

Here is the Full working code in Swift


import SwiftUI
import WebKit
import Photos

struct ContentView: View {
    @State private var showingAlert = false
    @State private var alertMessage = ""
    
    var body: some View {
        ZStack {
            // WebView
            WebView()
                .ignoresSafeArea()
            
            // Capture Button
            VStack {
                HStack {
                    Spacer()
                    Button(action: captureWebView) {
                        Image(systemName: "camera.fill")
                            .font(.title2)
                            .foregroundColor(.white)
                            .frame(width: 50, height: 50)
                            .background(Color.blue)
                            .clipShape(Circle())
                            .shadow(radius: 5)
                    }
                    .padding(.trailing, 20)
                }
                Spacer()
            }
            .padding(.top, 50)
        }
        .alert("Capture Result", isPresented: $showingAlert) {
            Button("OK") { }
        } message: {
            Text(alertMessage)
        }
    }
    
    private func captureWebView() {
        guard let webView = webView else {
            alertMessage = "WebView not ready"
            showingAlert = true
            return
        }
        
        // Wait for the page to load if it's still loading
        if webView.isLoading {
            alertMessage = "Please wait for the page to finish loading"
            showingAlert = true
            return
        }
        
        let configuration = WKSnapshotConfiguration()
        configuration.rect = webView.bounds
        webView.takeSnapshot(with: configuration) { image, error in
            if let error = error {
                alertMessage = "Failed to capture: \(error.localizedDescription)"
                showingAlert = true
                return
            }
            
            guard let image = image else {
                alertMessage = "Failed to generate image"
                showingAlert = true
                return
            }
            
            saveImageToPhotoLibrary(image)
        }
    }
    
    /// Saves photos to photo library
    /// - Parameter image: image
    /// - NOTE: You need to add `NSPhotoLibraryUsageDescription` and `NSPhotoLibraryAddUsageDescription` in info.plist
    private func saveImageToPhotoLibrary(_ image: UIImage) {
        PHPhotoLibrary.requestAuthorization { status in
            DispatchQueue.main.async {
                switch status {
                case .authorized, .limited:
                    PHPhotoLibrary.shared().performChanges({
                        PHAssetChangeRequest.creationRequestForAsset(from: image)
                    }) { success, error in
                        DispatchQueue.main.async {
                            if success {
                                alertMessage = "Image saved to photo library successfully!"
                            } else if let error = error {
                                alertMessage = "Failed to save image: \(error.localizedDescription)"
                            } else {
                                alertMessage = "Failed to save image"
                            }
                            showingAlert = true
                        }
                    }
                case .denied, .restricted:
                    alertMessage = "Photo library access denied"
                    showingAlert = true
                case .notDetermined:
                    alertMessage = "Photo library access not determined"
                    showingAlert = true
                @unknown default:
                    alertMessage = "Unknown photo library status"
                    showingAlert = true
                }
            }
        }
    }
}

var webView: WKWebView?

struct WebView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> WKWebView {
        let configuration = WKWebViewConfiguration()
        configuration.allowsInlineMediaPlayback = true
        
        webView = WKWebView(frame: .zero, configuration: configuration)
        
        // Load a default webpage
        if let url = URL(string: "https://www.apple.com") {
            let request = URLRequest(url: url)
            webView!.load(request)
        }
        
        return webView!
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        // Update UI if needed
    }
}

#Preview {
    ContentView()
}

3 Comments

I used this API, but the problem is not just that. I'm very sorry for not being clear. My webview is within a tableview list, and it is part of the list. This means that when I scroll the list, it may appear at any position on the screen. At this time, there are webviews and other cells on the screen simultaneously. My goal is to take a screenshot of the content within the screen, regardless of what it is - whether it's a webview, a cell, or both.
Then, please update your question, and provide minimum reproducible project
Thank you very much for your help, bro. I just found a solution, which is to use the -(BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates API. This has solved the problem that has been bothering me for several days.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.