Convert SwiftUI View to NSImage
Asked Answered
B

1

10

How can I create a SwiftUI View extension to return a NSImage? I have seen how it can be done on iOS using UIGraphicsImageRenderer but it seems there is no macOS equivalent.

Betteann answered 24/9, 2021 at 11:51 Comment(0)
T
16

View+Image.swift

import SwiftUI

extension View {
    
    func renderAsImage() -> NSImage? {
        let view = NoInsetHostingView(rootView: self)
        view.setFrameSize(view.fittingSize)
        return view.bitmapImage()
    }

}

NoInsetHostingView.swift

import SwiftUI

class NoInsetHostingView<V>: NSHostingView<V> where V: View {
    
    override var safeAreaInsets: NSEdgeInsets {
        return .init()
    }
    
}

NSView+Image.swift

public extension NSView {
    
    func bitmapImage() -> NSImage? {
        guard let rep = bitmapImageRepForCachingDisplay(in: bounds) else {
            return nil
        }
        cacheDisplay(in: bounds, to: rep)
        guard let cgImage = rep.cgImage else {
            return nil
        }
        return NSImage(cgImage: cgImage, size: bounds.size)
    }
    
}

I'm not sure exactly why NoInsetHostingView is needed, but with just a normal NSHostingView the image has undesired insets, and this fixes it.

Tortuosity answered 24/9, 2021 at 12:29 Comment(1)

© 2022 - 2024 — McMap. All rights reserved.