Search code examples
swiftuisprite-kit

How to create an UIImage from the contents of a SpriteView


I'd like to ultimately save a SpriteView as a photo. The issue is that I'm going nowhere with it. For clarity GridView is essentially an SKScene which is then wrapped by a SpriteView in WallpaperView.

If I try to use ImageRenderer in wallpaper view directly I get Unable to render flattened version of PlatformViewRepresentableAdaptor<UIKitSpriteKitView>.

And in the example below, I get a 30x30 image with, yellow background and red X.

Is what I'm trying to do even possible?

struct WallpaperView: View {
    let grid = Grid(density: 256, contents: ["1", "2", "3", "4"])
    let cellSizeRange: ClosedRange<CGFloat> = (1...4)
    var body: some View {
        GeometryReader { geometry in
            SpriteView(scene: GridView(grid: grid, cellSizeRange: cellSizeRange, size: geometry.size))
        }
        .ignoresSafeArea()
    }
}


struct ContentView: View {
    var body: some View {
        let wallpaperView = WallpaperView()
        ZStack {
            wallpaperView
            Button("Export", action: {
                let renderer = ImageRenderer(content: wallpaperView)
                renderer.scale = 3
                let image = renderer.uiImage
                UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
            })
        }
    }
}

Solution

  • You can use SKView's texture(from:) to render the contents of the SKScene (GridView) into an SKTexture and then use SKTexture's cgImage() in an UIImage(cgImage:).

    Something like this:

    guard let texture = gridView.view?.texture(from: gridView) else { return UIImage() }
    return UIImage(cgImage: texture.cgImage())