swiftswiftuisprite-kitwidgetkitwidgetliveactivity

SwiftUI cannot show SpriteView in live activities


I am trying to show a sprite view in an app. I already have it showing as a view on the main app and it works perfectly fine. The problem comes when I try and add it as a view using

var characterView: some View {
        SpriteView(scene: characterScene)
            .frame(width: 50, height: 50)
    }

and just showing that view.

Here is some minimal code:

// Character Animation
import Foundation
import SpriteKit

class CharacterScene: SKScene {
    let characterName: String
    init(characterName: String) {
        self.characterName = characterName
        super.init(size: CGSize(width: 300, height: 400))
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    var textures: [SKTexture] = []
    override func didMove(to view: SKView) {
        let atlas = SKTextureAtlas(named: characterName)
        textures = atlas.textureNames.sorted().map { atlas.textureNamed($0) }
        
        let sprite = SKSpriteNode(texture: textures[0])
        let maxSize: CGFloat = 200
        let aspectRatio = sprite.size.height / sprite.size.width
        sprite.size = CGSize(width: min(sprite.size.width, maxSize), height: min(sprite.size.height, maxSize * aspectRatio))
        sprite.position = CGPoint(x: frame.midX, y: frame.midY)
        addChild(sprite)
        
        let animation = SKAction.animate(with: textures, timePerFrame: 0.5)
        sprite.run(SKAction.repeatForever(animation))
    }
}

//Widget

import WidgetKit
import SwiftUI
import ActivityKit
import SpriteKit

struct CharacterIslandWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(
            for: CharacterIslandAttributes.self,
            content: { context in
                CharacterIslandWidgetView(context: context)
            },
            dynamicIsland: { context in
                DynamicIsland(
                    expanded: {
                        DynamicIslandExpandedRegion(.center) {
                            Text(context.state.CharacterName)
                        }
                        DynamicIslandExpandedRegion(.leading) {
                            SpriteView(scene: CharacterScene(characterName: context.state.CharacterImage))
                                .frame(width: 50, height: 50)
                        }
                    },
                    compactLeading: {
                        SpriteView(scene: CharacterScene(characterName: context.state.CharacterImage))
                            .frame(width: 50, height: 50)
                    },
                    compactTrailing: {
                    },
                    minimal: {
                        SpriteView(scene: CharacterScene(characterName: context.state.CharacterImage))
                            .frame(width: 50, height: 50)
                    })
            }
    )}
}
struct CharacterIslandWidgetView: View {
    let context: ActivityViewContext<CharacterIslandAttributes>
    var body: some View {
        SpriteView(scene: CharacterScene(characterName: context.state.CharacterImage))
            .frame(width: 50, height: 50)
        Text(context.state.CharacterImage)
    }
}

I don't get any executable errors in the logs, so I don't exactly know the problem, but the image looks like this (I don't have previews set up for the widgets yet).

image error

The atlas name is given below the image and is correct as it is running perfectly fine in the app.

A few extra things:

How do I go about this from here? Are sprite views not allowed in Live Activities (Dynamic Island)?

I tried hardcoding names, and reading error logs, but nothing showed.


Solution

  • Widgets only support a subset of SwiftUI views and live activities are a special kind of widget. Apple documents the SwiftUI views that can be used in widgets.

    The red no entry symbol seems to be displayed when trying to use an unsupported SwiftUI view (Why do some views appear as a red no entry sign in widgets?)