Xcode提示:’@StateObject’ used inline will not work unless tagged with ‘@Previewable’ (from macro ‘Preview’)
Xcode提示:’@StateObject’ used inline will not work unless tagged with ‘@Previewable’ (from macro ‘Preview’)

Xcode提示:’@StateObject’ used inline will not work unless tagged with ‘@Previewable’ (from macro ‘Preview’)

在Xcode预览视图代码中,提示:

'@StateObject' used inline will not work unless tagged with '@Previewable' (from macro 'Preview')

这个错误来自Xcode 16 / iOS 18 SDK中SwiftUI预览机制的更新。

在旧版本(Xcode 15及以前),可以正常工作。但是从Xcode 16开始,苹果修改了 #Preview 宏的行为,导致在 #Preview 中不再被允许声明 @StateObject。

'@StateObject' used inline will not work unless tagged with '@Previewable'

这个代码的意思为,不能在 #Preview {} 预览视图代码中直接创建@StateObject。

除非把这个结构体或变量标记为 @Previewable(但这个宏仅供系统内部使用,目前不公开)。

解决方案

将 @StateObject 的逻辑放入一个单独的预览容器中:

#Preview {
    PreviewWrapper()
}

struct PreviewWrapper: View {
    @StateObject private var iapManager = IAPManager.shared
    
    var body: some View {
        ContentView()
            .environmentObject(iapManager)
            .task {
                await iapManager.loadProduct()
                await iapManager.handleTransactions()
            }
    }
}

这个写法兼容Xcode 15和Xcode 16,也不会触发”@StateObject used inline”的编译报错。

@Previewable修饰符

如果想要使用苹果新增的@Previewable修饰符,就需要在预览视图前面添加@Previewable。

#Preview {
    ContentPreview()
}

@Previewable
struct ContentPreview: View {
    @StateObject var iapManager = IAPManager.shared

    var body: some View {
        ContentView()
            .environmentObject(iapManager)
            .task {
                await iapManager.loadProduct()
                await iapManager.handleTransactions()
            }
    }
}

需要注意的一点,@Previewable仅支持iOS17及以上的Xcode预览设备。

'@Previewable' can only be used in a #Preview body closure (from macro 'Previewable')
'Previewable()' is only available in iOS 17.0 or newer

如果项目的最低部署目标(Depolyment Target)小于iOS 17,就需要进行iOS版本的条件判断。

因此,在iOS 15+的项目里预览SwiftUI视图,不建议使用 @Previewable。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注