My view doesn't have a black background when displayed, but after saving it as an image, the content of the view is reduced, and a black background appears above it.

View display on iPhone my view

Export View to Image view to image

Here's the whole code.

import Foundation
import Photos
import SwiftUI
import UIKit
struct MyImageView: View {
    @State private var image: UIImage?
    @State var viewWidth = 0.0
    @State var viewHeight = 0.0
    @ObservedObject var imageSaver = ImageSaver()

    var imageUrl = "https://pic.netbian.com/uploads/allimg/160709/215802-1468072682c2c8.jpg"
    
    func calculateSize() {
        let maxWidth = UIScreen.main.bounds.width
        let maxHeight = UIScreen.main.bounds.height - 100
        if maxHeight/maxWidth >= image!.size.height/image!.size.width {
            viewWidth = maxWidth
            viewHeight = maxWidth * image!.size.height/image!.size.width
        } else {
            viewHeight = maxHeight
            viewWidth = maxHeight/(image!.size.height/image!.size.width)
        }
    }

    private func loadImage() {
        URLSession.shared.dataTask(with: URL(string: imageUrl)!) { data, _, error in
            guard let data = data, error == nil else {
                print("Error loading image: \(error?.localizedDescription ?? "Unknown error")")
                return
            }

            if let uiImage = UIImage(data: data) {
                DispatchQueue.main.async {
                    self.image = uiImage
                    calculateSize()
                }
            } else {
                print("Failed to create image from data")
            }
        }.resume()
    }

    var myView: some View {
        ZStack {
            if self.image != nil {
                Image(uiImage: self.image!)
                    .resizable()
                    .frame(width: viewWidth, height: viewHeight)
            }
            Text("hello girl").font(.title).foregroundColor(.red)
        }.frame(width: viewWidth, height: viewHeight)
            .background(Color.black)
            .onAppear {
                loadImage()
            }
    }

    var body: some View {
        VStack {
            myView
            Button("save image") {
                myView.snapshot { image in
                    if let image = image {
                        imageSaver.saveSnapshot(compressedImage: image)
                    } else {
                        print("Failed to capture snapshot image.")
                    }
                }
            }
        }
    }
}

extension View {
    func snapshot(completion: @escaping (UIImage?) -> Void) {
        let controller = UIHostingController(rootView: self)
        let view = controller.view
        view?.translatesAutoresizingMaskIntoConstraints = false
        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .black
        view?.layoutIfNeeded()
        let renderer = UIGraphicsImageRenderer(size: targetSize)
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            let image: UIImage = renderer.image { _ in
                controller.view.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
            }
            controller.view.removeFromSuperview()
            completion(image)
        }
    }
}

class ImageSaver: NSObject, ObservableObject {
    @Published var isPresented = false
    @Published var title: String = ""
    @Published var message: String = ""

    func saveSnapshot(compressedImage: UIImage) {
        PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in
            switch status {
            case .authorized:
                UIImageWriteToSavedPhotosAlbum(
                    compressedImage, self, #selector(self.saveError), nil
                )
            case .denied:
                self.title = NSLocalizedString("access_denied", comment: "")
                self.message =
                    NSLocalizedString("snapshot_saver_1", comment: "")
                self.isPresented = true
                print("access denied")
            case .limited:
                self.title = NSLocalizedString("snapshot_saver_2", comment: "")
                self.message =
                    NSLocalizedString("snapshot_saver_1", comment: "")
                self.isPresented = true
                print("limited access only")
            case .notDetermined:
                print("access not determined")
            case .restricted:
                print("access restricted")
            @unknown default:
                break
            }
        }
    }

    @objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
        isPresented = true
        if error != nil {
            title = "failed"
            message = "save image failed"

        } else {
            title = "success"
            message = "save image success"
        }
    }
}

#Preview {
    MyImageView()
}

To ensure a perfect consistency between the displayed view and the exported image, I have fixed the width and height of the view.

0

There are 0 best solutions below