Xcode提示:Cannot use instance member ‘defaultWakeTime’ within property initializer; property initializers run before ‘self’ is available
Xcode提示:Cannot use instance member ‘defaultWakeTime’ within property initializer; property initializers run before ‘self’ is available

Xcode提示:Cannot use instance member ‘defaultWakeTime’ within property initializer; property initializers run before ‘self’ is available

问题复现

在Xcode中,存在“Cannot use instance member ‘defaultWakeTime’ within property initializer; property initializers run before ‘self’ is available”报错提示。

在于Swift的struct中,属性初始化的顺序需要严格遵守。这个错误是由于Swift视图在属性中使用另一个属性,违反了Swift的规则。

具体来讲就是,Swift不允许直接从另一个属性中获取默认值,因为Swift不知道这些属性初始化的顺序。在本次报错中就是声明@State private var wakeUp的时候,试图直接调用defaultWakeTime,而defaultWakeTime本身是一个计算属性,Swift无法保证这两个属性的创建顺序。

解决方案

方案一(使用静态属性)

将 defaultWakeTime 改为

var defaultWakeTime: Date {             // 修改前
static var defaultWakeTime: Date {     // 修改后

将 defaultWakeTime声明改为静态属性,可以避免Swift对于属性顺序化的限制,原因在于,Swift中静态属性属于类型本身,而不属于类型的某个实例,所以不依赖某个实例的存在状态,可以随时读取,因此可以绕过属性初始化顺序的问题。

方法二(使用onAppear)

在视图的onAppear方法中设置wakeUp的初始值,而不是在声明时直接初始化。

struct ContentView: View {
    @State private var wakeUp = Date.now
    
    var defaultWakeTime: Date {
        ...     // 其他代码
    }

    var body: some View {
        VStack {
            DatePicker("Please select a time", selection: $wakeUp, displayedComponents: .hourAndMinute)
                .labelsHidden()
        }
        .onAppear {
            wakeUp = defaultWakeTime    // 在 onAppear中设置初始值
        }
    }
}

方法三(在init方法中设置)

在 View 的 init 方法中设置 wakeUp 的初始值

struct ContentView: View {
    @State private var wakeUp = Date.now
    
    var defaultWakeTime: Date {
        ...     // 其他代码
    }

    init() {
        _wakeUp = State(initialValue: defaultWakeTime)  // 在init方法中设置
    }

    var body: some View {
        ...
    }
}

_wakeUp 是 @State 包装器的实际存储属性。使用 _ 前缀可以访问包装器实例本身,而不是包装器管理的值(即 wakeUp)。

State(initialValue:) 是 State 属性包装器的初始化方法,用于设置 @State 属性的初始值。这里通过 State(initialValue: ContentView.defaultWakeTime) 来将 defaultWakeTime 作为初始值赋给 wakeUp 状态。

参考资料

清理用户界面:https://www.hackingwithswift.com/books/ios-swiftui/cleaning-up-the-user-interface

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

发表回复

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