SwiftUI Live Activities无法显示SpriteView问题求助
SpriteView在Live Activities(Dynamic Island)中无法正常显示的问题
我在主App中使用SpriteView显示精灵动画完全正常,但将其添加到Live Activities(Dynamic Island)后出现显示异常,日志无执行错误。相关代码片段如下:
var characterView: some View { SpriteView(scene: characterScene) .frame(width: 50, height: 50) }
以下是完整的最小化代码示例:
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) } }
问题补充
图集名称正确,资源文件夹已在App和Widget间共享,context.state.CharacterImage为包含所有精灵的图集文件夹名称。尝试过硬编码名称、查看错误日志均无结果,想确认SpriteView是否不允许在Live Activities(Dynamic Island)中使用,以及对应的解决办法。
问题原因与解决方案
核心原因
SpriteKit(包括SpriteView)目前不支持在Live Activities/Dynamic Island中使用。苹果的WidgetKit和ActivityKit框架对Live Activities可使用的视图类型有严格限制,所有基于UIKit/AppKit的封装视图(包括SpriteView)都无法在Live Activities环境中正常渲染。
替代方案1:SwiftUI原生逐帧动画
将精灵图集的图片拆分为单独序列帧,用SwiftUI的Timer和Image实现逐帧动画:
struct AnimatedCharacterView: View { let frameNames: [String] // 图集内所有图片的名称数组 @State private var currentFrameIndex = 0 var body: some View { Image(frameNames[currentFrameIndex]) .resizable() .scaledToFit() .frame(width: 50, height: 50) .onAppear { // 每0.5秒切换一帧,循环播放 Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in currentFrameIndex = (currentFrameIndex + 1) % frameNames.count } } } }
使用时,传入图集的图片名称数组即可,需确保这些图片资源已添加到Widget的Target Membership中。
替代方案2:预渲染视频+VideoPlayer播放
将精灵动画预渲染为循环短视频(如MP4格式),在Live Activities中用VideoPlayer播放:
import AVKit struct AnimatedCharacterVideoView: View { private let videoURL: URL init(videoName: String) { // 从Widget资源中获取视频URL self.videoURL = Bundle.main.url(forResource: videoName, withExtension: "mp4")! } var body: some View { VideoPlayer(player: createLoopPlayer()) .frame(width: 50, height: 50) .scaledToFit() } private func createLoopPlayer() -> AVPlayer { let player = AVPlayer(url: videoURL) // 设置播放完成后循环 player.actionAtItemEnd = .none NotificationCenter.default.addObserver( forName: .AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: .main ) { _ in player.seek(to: .zero) player.play() } player.play() return player } }
需提前将动画转成视频文件,并确保视频资源已加入Widget的Target Membership。
关键注意事项
- Live Activities仅支持有限的原生SwiftUI组件,例如
Text、Image、ProgressView、VideoPlayer等,第三方或封装视图无法正常工作。 - 所有资源(图片/视频)必须在Xcode中勾选Widget的
Target Membership,否则Widget无法访问到资源。
内容的提问来源于stack exchange,提问作者Wamy-Dev
相关产品推荐
相关产品推荐

