Saturday, December 21, 2024
HomeiOS Developmentios - Changing Many Views into Picture Knowledge in Thread

ios – Changing Many Views into Picture Knowledge in Thread

[ad_1]

I’ve a undertaking that turns views I create within the undertaking into Pictures then takes the pngImageData of these views and uploads it as Pictures to my server. All of it takes place with out displaying the views being generated and works terrifically. Nonetheless I would really like to have the ability to generate hundreds of those pictures at a time. Presently I name the next View extension

func getDataForFBS(width: CGFloat, top: CGFloat, _ completion: @escaping (Knowledge?) -> Void) {
    let dimension = CGSize(width: width, top: top)
    let controller = UIHostingController(rootView: self.body(width: dimension.width, top: dimension.top))
    controller.view.bounds = CGRect(origin: .zero, dimension: dimension.making use of(.init(scaleX: 1.1, y: 1.1)))
    controller.view.backgroundColor = UIColor.clear
    completion(controller.view?.getImageFromCurrentContext()?.pngData())
}

which converts the View to a UIView earlier than utilizing this UIView extension

func getImageFromCurrentContext(bounds: CGRect? = nil) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(bounds?.dimension ?? self.bounds.dimension, false, 0.0)
    self.drawHierarchy(in: bounds ?? self.bounds, afterScreenUpdates: true)
    guard let currentImage = UIGraphicsGetImageFromCurrentImageContext() else {
        return nil
    }
    UIGraphicsEndImageContext()
    return currentImage
}

which passes again a UIImage to name .pngData() on within the first extensions completion which I then add to my sever if the end result shouldn’t be nil.

This works nice if I solely cross in a couple of Views at a time, nevertheless it hangs the Foremost thread and inevitably crashes the complete utility if I cross in additional than about 200 without delay. I’ve tried wrapping the loop performing this in a Process, a persistent containers performBackgroundTask in addition to a plain previous DispatchQueue.world(qos: .userInitiated).async() nevertheless my getImageFromCurrentContext UIView extension calls self.drawHierarchy which may solely be carried out on the Foremost UI thread.

I discovered this UIView extension on-line that doesn’t require the Foremost UI thread

func asImageAsync(dimension: CGSize? = nil) -> UIImage {
    let format = UIGraphicsImageRendererFormat()
    format.scale = 1
    return UIGraphicsImageRenderer(dimension: dimension ?? self.bounds.dimension, format: format).picture { context in
        layer.render(in: context.cgContext)
    }
}

because it replaces self.drawHierarchy with that layer.render line which iOS doesn’t appear to thoughts being known as from a background thread. This works nice if I name it from the principle thread and can show the UIImage I make from the info simply tremendous. Nonetheless, if I thread out the method, it completes virtually instantly and though all of the file situations are created on my server and present an affordable file dimension for every, the precise picture is non-existent and I find yourself with a ton of clean pictures.

Is there any approach to get pngImageData from a whole bunch of SwiftUI views asynchronously? As I discussed I am not really displaying the views simply; instantiating an occasion of every one after the other passing in a contemporary fixed that determines what the view shows then, calling getDataForFBS on every and pushing the end result as much as my server if it isn’t nil. I assumed as a result of I do not really present every view this might be straightforward to perform with out the usage of the UI thread, however I’ve been making an attempt for days now and have but to search out or work out an answer.

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments