简体   繁体   中英

Rendering a View as an image in SwiftUI project

I am currently handling an end-to-end SwiftUI project which involves a ClockKit complication. As one of complication's templates requires an image (UIImage) I need to render (snapshot) an existing SwiftUI View to an image. I have found a couple of possible solutions to this problem, including the following View extension:

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)

        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

The problem I have is that wherever I implement this extension I keep getting "not in scope" Xcode errors ( "Cannot find 'UIHostingController' in scope", "Cannot find 'UIGraphicsImageRenderer' in scope", "Cannot infer contextual base in reference to member 'clear'" ).

SwiftUI and UIKit are imported in these Swift files (but I think the latter shouldn't be necessary). Xcode 12.5.

Please do share some tips that could help overcome this hurdle... I am a rather inexperienced developer and I could be missing something rather obvious, but at this point I'm pulling my hair out. Whenever I implement a reasonable solution that happened to be in other questions or websites it always comes to UIKit specific commands not being in scope.

Edit : So it turns out this extension works only if implemented in main ContentView for iOS target. Does not work if put in any other directory. However I need this extension to work in files of (watchOS) Extension files (as I said it's needed for CK Complication) and it's not possible to set target membership of the main iOS ContentView also for (watchOS) Extension, as then two ContentViews would apply to one watchOS version and error occurs. How then effectively place the above extension code so it could apply for where it's needed?

The problem for the errors pop up (like Cannot find UIHostingController in scope and others) is because UIHostingController and UIGraphicsImageRenderer are not available on watchOS, meaning the extension, as written, will not compile on that platform.

Refer to my other answered question .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM