错误无法在 属性 初始值设定项中使用实例成员 'xxx'
Error Cannot use instance member 'xxx' within property initializer
26-07-19
我会在观看 WWDC 视频的过程中更新我的代码。我的数据模型是:
struct Egg: Identifiable {
var id = UUID()
var thumbnailImage: String
var day: String
var date: String
var text: String
var imageDetail: String
var weight: Double
}
#if DEBUG
let testData = [
Egg(thumbnailImage: "Dag-1", day: "1.circle", date: "7 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-1", weight: 35.48),
Egg(thumbnailImage: "Dag-2", day: "2.circle", date: "8 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-2", weight: 35.23),
Egg(thumbnailImage: "Dag-3", day: "3.circle", date: "9 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-3", weight: 34.92)
Etc, etc
]
我有一个 TabbedView、一个 ContentView、一个 ContentDetail 和几个其他视图(用于设置等)。 ContentView 的代码是:
struct ContentView : View {
var eggs : [Egg] = []
var body: some View {
NavigationView {
List(eggs) { egg in
EggCell(egg: egg)
}
.padding(.top, 10.0)
.navigationBarTitle(Text("Egg management"), displayMode: .inline)
}
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView(eggs: testData)
}
}
#endif
struct EggCell : View {
let egg: Egg
var body: some View {
return NavigationLink(destination: ContentDetail(egg: egg)) {
ZStack {
HStack(spacing: 8.0) {
Image(egg.thumbnailImage)
.resizable()
.aspectRatio(contentMode: .fit)
.padding(.leading, -25)
.padding(.top, -15)
.padding(.bottom, -15)
.padding(.trailing, -25)
.frame(width: 85, height: 61)
VStack {
Image(systemName: egg.day)
.resizable()
.frame(width: 30, height: 22)
.padding(.leading, -82)
Spacer()
}
.padding(.leading)
VStack {
Text(egg.date)
.font(.headline)
.foregroundColor(Color.gray)
Text(egg.weight.clean)
.font(.title)
}
}
}
}
}
}
extension Double {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
}
}
ContentDetail 的代码是:
struct ContentDetail : View {
let egg: Egg
@State private var photo = true
@State private var calculated = false
@Binding var weight: Double
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(egg.date)
.font(.title)
.fontWeight(.medium)
.navigationBarTitle(Text(egg.date), displayMode: .inline)
ZStack (alignment: .topLeading) {
Image(photo ? egg.imageDetail : egg.thumbnailImage)
.resizable()
.aspectRatio(contentMode: .fill)
.background(Color.black)
.padding(.trailing, 0)
.tapAction { self.photo.toggle() }
VStack {
HStack {
Image(systemName: egg.day)
.resizable()
.padding(.leading, 10)
.padding(.top, 10)
.frame(width: 50, height: 36)
.foregroundColor(.white)
Spacer()
Image(systemName: photo ? "photo" : "wand.and.stars")
.resizable()
.padding(.trailing, 10)
.padding(.top, 10)
.frame(width: 50, height: 36)
.foregroundColor(.white)
}
Spacer()
HStack {
Image(systemName: "arrow.left.circle")
.resizable()
.padding(.leading, 10)
.padding(.bottom, 10)
.frame(width: 50, height: 50)
.foregroundColor(.white)
Spacer()
Image(systemName: "arrow.right.circle")
.resizable()
.padding(.trailing, 10)
.padding(.bottom, 10)
.frame(width: 50, height: 50)
.foregroundColor(.white)
}
}
}
Text("the weight is: \(egg.weight) gram")
.font(.headline)
.fontWeight(.bold)
ZStack {
RoundedRectangle(cornerRadius: 10)
.padding(.top, 45)
.padding(.bottom, 45)
.border(Color.gray, width: 5)
.opacity(0.1)
HStack {
Spacer()
DigitPicker(digitName: "tens", digit: $weight.tens)
DigitPicker(digitName: "ones", digit: $weight.ones)
Text(".")
.font(.largeTitle)
.fontWeight(.black)
.padding(.bottom, 10)
DigitPicker(digitName: "tenths", digit: $weight.tenths)
DigitPicker(digitName: "hundredths", digit: $weight.hundredths)
Spacer()
}
}
Toggle(isOn: $calculated) {
Text(calculated ? "This weight is calculated." : "This weight is measured.")
}
Text(egg.text)
.lineLimit(2)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
Spacer()
}
.padding(6)
}
}
#if DEBUG
struct ContentDetail_Previews : PreviewProvider {
static var previews: some View {
NavigationView { ContentDetail(egg: testData[0]) }
}
}
#endif
struct DigitPicker: View {
var digitName: String
@Binding var digit: Int
var body: some View {
VStack {
Picker(selection: $digit, label: Text(digitName)) {
ForEach(0 ... 9) {
Text("\([=14=])").tag([=14=])
}
}.frame(width: 60, height: 110).clipped()
}
}
}
fileprivate extension Double {
var tens: Int {
get { sigFigs / 1000 }
set { replace(tens: newValue) }
}
var ones: Int {
get { (sigFigs / 100) % 10 }
set { replace(ones: newValue) }
}
var tenths: Int {
get { (sigFigs / 10) % 10 }
set { replace(tenths: newValue) }
}
var hundredths: Int {
get { sigFigs % 10 }
set { replace(hundredths: newValue) }
}
private mutating func replace(tens: Int? = nil, ones: Int? = nil, tenths: Int? = nil, hundredths: Int? = nil) {
self = Double(0
+ 1000 * (tens ?? self.tens)
+ 100 * (ones ?? self.ones)
+ 10 * (tenths ?? self.tenths)
+ (hundredths ?? self.hundredths)) / 100.0
}
private var sigFigs: Int {
return Int((self * 100).rounded(.toNearestOrEven))
}
}
我仍然遇到的编译器错误是:
- 在 ContentView 中,NavigationLink 下方:缺少参数
调用
中的参数 'weight'
- 在 NavigationView 的 ContentDetail 中:缺少参数参数
'weight' 通话中
- 在 ContentDetail 中,#endif 之后:参数缺少参数
'weight' 通话中
25-07-19
以下代码是列表详细信息视图的一部分。 var 'weight' 通过 'NavigationLink' 语句来自列表。在此代码中,我将其声明为“35.48”,但 NavigationLink 填写了它的实际值。
我想用 compactMap 语句创建一个数组 [3, 5, 4, 8]。这在 Playground 中工作正常。这些值转到 4 个不同的选择器(在 HStack 中)。
import SwiftUI
import Foundation
struct ContentDetail : View {
var weight : Double = 35.48
var weightArray = "\(weight)".compactMap { Int("\([=15=])") }
@State var digit1 = weightArray[0] // error
@State var digit2 = weightArray[1] // error
@State var digit3 = weightArray[2] // error
@State var digit4 = weightArray[3] // error
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(weight)
.font(.title)
.fontWeight(.medium)
etc etc
我收到错误“无法在 属性 初始值设定项中使用实例成员 'weightArray'; 属性 初始值设定项 运行 在 'self' 可用之前'。
如果我使用下面的代码,它工作正常(对于第一个列表元素):
import SwiftUI
import Foundation
struct ContentDetail : View {
var weight : Double = 35.48
var weightArray = [3, 5, 4, 8]
@State var digit1 = 3
@State var digit2 = 5
@State var digit3 = 4
@State var digit4 = 8
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(weight)
.font(.title)
.fontWeight(.medium)
etc etc
什么是正确的 SwiftUI 方法,为什么?
确实,属性 初始化程序不能引用同一容器中的另一个 属性。您必须在 init
中初始化您的属性。
struct ContentDetail: View {
var weight: Double
var weightArray: [Int]
@State var digit1: Int
@State var digit2: Int
@State var digit3: Int
@State var digit4: Int
init(weight: Double) {
self.weight = weight
weightArray = "\(weight)".compactMap { Int("\([=10=])") }
_digit1 = .init(initialValue: weightArray[0])
_digit2 = .init(initialValue: weightArray[1])
_digit3 = .init(initialValue: weightArray[2])
_digit4 = .init(initialValue: weightArray[3])
}
但我怀疑您要拆分数字是因为您想让用户单独编辑它们,如下所示:
如果那是你想要的,你不应该为每个数字单独设置 @State
属性。相反,weight
应该是 @Binding
并且每个数字应该有一个单独的可变 属性。
首先,扩展 Double
以允许您访问数字:
fileprivate extension Double {
var tens: Int {
get { sigFigs / 1000 }
set { replace(tens: newValue) }
}
var ones: Int {
get { (sigFigs / 100) % 10 }
set { replace(ones: newValue) }
}
var tenths: Int {
get { (sigFigs / 10) % 10 }
set { replace(tenths: newValue) }
}
var hundredths: Int {
get { sigFigs % 10 }
set { replace(hundredths: newValue) }
}
private mutating func replace(tens: Int? = nil, ones: Int? = nil, tenths: Int? = nil, hundredths: Int? = nil) {
self = Double(0
+ 1000 * (tens ?? self.tens)
+ 100 * (ones ?? self.ones)
+ 10 * (tenths ?? self.tenths)
+ (hundredths ?? self.hundredths)) / 100.0
}
private var sigFigs: Int {
return Int((self * 100).rounded(.toNearestOrEven))
}
}
然后,将 ContentDetail
的 weight
属性 更改为 @Binding
并去掉其他属性:
struct ContentDetail: View {
@Binding var weight: Double
var body: some View {
HStack {
DigitPicker(digitName: "tens", digit: $weight.tens)
DigitPicker(digitName: "ones", digit: $weight.ones)
DigitPicker(digitName: "tenths", digit: $weight.tenths)
DigitPicker(digitName: "hundredths", digit: $weight.hundredths)
}
}
}
struct DigitPicker: View {
var digitName: String
@Binding var digit: Int
var body: some View {
VStack {
Picker(selection: $digit, label: Text(digitName)) {
ForEach(0 ... 9) {
Text("\([=12=])").tag([=12=])
}
}.frame(width: 60, height: 110).clipped()
}
}
}
下面是在操场上测试它所需的其余代码,这就是我生成上面那张图片的方式:
import PlaygroundSupport
struct TestView: View {
@State var weight: Double = 35.48
var body: some View {
VStack(spacing: 0) {
Text("Weight: \(weight)")
ContentDetail(weight: $weight)
.padding()
}
}
}
let host = UIHostingController(rootView: TestView())
host.preferredContentSize = .init(width: 320, height: 240)
PlaygroundPage.current.liveView = host
26-07-19
我会在观看 WWDC 视频的过程中更新我的代码。我的数据模型是:
struct Egg: Identifiable {
var id = UUID()
var thumbnailImage: String
var day: String
var date: String
var text: String
var imageDetail: String
var weight: Double
}
#if DEBUG
let testData = [
Egg(thumbnailImage: "Dag-1", day: "1.circle", date: "7 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-1", weight: 35.48),
Egg(thumbnailImage: "Dag-2", day: "2.circle", date: "8 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-2", weight: 35.23),
Egg(thumbnailImage: "Dag-3", day: "3.circle", date: "9 augustus 2019", text: "Kippen leggen iedere dag een ei.", imageDetail: "Day-3", weight: 34.92)
Etc, etc
]
我有一个 TabbedView、一个 ContentView、一个 ContentDetail 和几个其他视图(用于设置等)。 ContentView 的代码是:
struct ContentView : View {
var eggs : [Egg] = []
var body: some View {
NavigationView {
List(eggs) { egg in
EggCell(egg: egg)
}
.padding(.top, 10.0)
.navigationBarTitle(Text("Egg management"), displayMode: .inline)
}
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView(eggs: testData)
}
}
#endif
struct EggCell : View {
let egg: Egg
var body: some View {
return NavigationLink(destination: ContentDetail(egg: egg)) {
ZStack {
HStack(spacing: 8.0) {
Image(egg.thumbnailImage)
.resizable()
.aspectRatio(contentMode: .fit)
.padding(.leading, -25)
.padding(.top, -15)
.padding(.bottom, -15)
.padding(.trailing, -25)
.frame(width: 85, height: 61)
VStack {
Image(systemName: egg.day)
.resizable()
.frame(width: 30, height: 22)
.padding(.leading, -82)
Spacer()
}
.padding(.leading)
VStack {
Text(egg.date)
.font(.headline)
.foregroundColor(Color.gray)
Text(egg.weight.clean)
.font(.title)
}
}
}
}
}
}
extension Double {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
}
}
ContentDetail 的代码是:
struct ContentDetail : View {
let egg: Egg
@State private var photo = true
@State private var calculated = false
@Binding var weight: Double
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(egg.date)
.font(.title)
.fontWeight(.medium)
.navigationBarTitle(Text(egg.date), displayMode: .inline)
ZStack (alignment: .topLeading) {
Image(photo ? egg.imageDetail : egg.thumbnailImage)
.resizable()
.aspectRatio(contentMode: .fill)
.background(Color.black)
.padding(.trailing, 0)
.tapAction { self.photo.toggle() }
VStack {
HStack {
Image(systemName: egg.day)
.resizable()
.padding(.leading, 10)
.padding(.top, 10)
.frame(width: 50, height: 36)
.foregroundColor(.white)
Spacer()
Image(systemName: photo ? "photo" : "wand.and.stars")
.resizable()
.padding(.trailing, 10)
.padding(.top, 10)
.frame(width: 50, height: 36)
.foregroundColor(.white)
}
Spacer()
HStack {
Image(systemName: "arrow.left.circle")
.resizable()
.padding(.leading, 10)
.padding(.bottom, 10)
.frame(width: 50, height: 50)
.foregroundColor(.white)
Spacer()
Image(systemName: "arrow.right.circle")
.resizable()
.padding(.trailing, 10)
.padding(.bottom, 10)
.frame(width: 50, height: 50)
.foregroundColor(.white)
}
}
}
Text("the weight is: \(egg.weight) gram")
.font(.headline)
.fontWeight(.bold)
ZStack {
RoundedRectangle(cornerRadius: 10)
.padding(.top, 45)
.padding(.bottom, 45)
.border(Color.gray, width: 5)
.opacity(0.1)
HStack {
Spacer()
DigitPicker(digitName: "tens", digit: $weight.tens)
DigitPicker(digitName: "ones", digit: $weight.ones)
Text(".")
.font(.largeTitle)
.fontWeight(.black)
.padding(.bottom, 10)
DigitPicker(digitName: "tenths", digit: $weight.tenths)
DigitPicker(digitName: "hundredths", digit: $weight.hundredths)
Spacer()
}
}
Toggle(isOn: $calculated) {
Text(calculated ? "This weight is calculated." : "This weight is measured.")
}
Text(egg.text)
.lineLimit(2)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.padding(.leading, 6)
Spacer()
}
.padding(6)
}
}
#if DEBUG
struct ContentDetail_Previews : PreviewProvider {
static var previews: some View {
NavigationView { ContentDetail(egg: testData[0]) }
}
}
#endif
struct DigitPicker: View {
var digitName: String
@Binding var digit: Int
var body: some View {
VStack {
Picker(selection: $digit, label: Text(digitName)) {
ForEach(0 ... 9) {
Text("\([=14=])").tag([=14=])
}
}.frame(width: 60, height: 110).clipped()
}
}
}
fileprivate extension Double {
var tens: Int {
get { sigFigs / 1000 }
set { replace(tens: newValue) }
}
var ones: Int {
get { (sigFigs / 100) % 10 }
set { replace(ones: newValue) }
}
var tenths: Int {
get { (sigFigs / 10) % 10 }
set { replace(tenths: newValue) }
}
var hundredths: Int {
get { sigFigs % 10 }
set { replace(hundredths: newValue) }
}
private mutating func replace(tens: Int? = nil, ones: Int? = nil, tenths: Int? = nil, hundredths: Int? = nil) {
self = Double(0
+ 1000 * (tens ?? self.tens)
+ 100 * (ones ?? self.ones)
+ 10 * (tenths ?? self.tenths)
+ (hundredths ?? self.hundredths)) / 100.0
}
private var sigFigs: Int {
return Int((self * 100).rounded(.toNearestOrEven))
}
}
我仍然遇到的编译器错误是:
- 在 ContentView 中,NavigationLink 下方:缺少参数 调用 中的参数 'weight'
- 在 NavigationView 的 ContentDetail 中:缺少参数参数 'weight' 通话中
- 在 ContentDetail 中,#endif 之后:参数缺少参数 'weight' 通话中
25-07-19
以下代码是列表详细信息视图的一部分。 var 'weight' 通过 'NavigationLink' 语句来自列表。在此代码中,我将其声明为“35.48”,但 NavigationLink 填写了它的实际值。
我想用 compactMap 语句创建一个数组 [3, 5, 4, 8]。这在 Playground 中工作正常。这些值转到 4 个不同的选择器(在 HStack 中)。
import SwiftUI
import Foundation
struct ContentDetail : View {
var weight : Double = 35.48
var weightArray = "\(weight)".compactMap { Int("\([=15=])") }
@State var digit1 = weightArray[0] // error
@State var digit2 = weightArray[1] // error
@State var digit3 = weightArray[2] // error
@State var digit4 = weightArray[3] // error
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(weight)
.font(.title)
.fontWeight(.medium)
etc etc
我收到错误“无法在 属性 初始值设定项中使用实例成员 'weightArray'; 属性 初始值设定项 运行 在 'self' 可用之前'。
如果我使用下面的代码,它工作正常(对于第一个列表元素):
import SwiftUI
import Foundation
struct ContentDetail : View {
var weight : Double = 35.48
var weightArray = [3, 5, 4, 8]
@State var digit1 = 3
@State var digit2 = 5
@State var digit3 = 4
@State var digit4 = 8
var body: some View {
VStack (alignment: .center, spacing: 10) {
Text(weight)
.font(.title)
.fontWeight(.medium)
etc etc
什么是正确的 SwiftUI 方法,为什么?
确实,属性 初始化程序不能引用同一容器中的另一个 属性。您必须在 init
中初始化您的属性。
struct ContentDetail: View {
var weight: Double
var weightArray: [Int]
@State var digit1: Int
@State var digit2: Int
@State var digit3: Int
@State var digit4: Int
init(weight: Double) {
self.weight = weight
weightArray = "\(weight)".compactMap { Int("\([=10=])") }
_digit1 = .init(initialValue: weightArray[0])
_digit2 = .init(initialValue: weightArray[1])
_digit3 = .init(initialValue: weightArray[2])
_digit4 = .init(initialValue: weightArray[3])
}
但我怀疑您要拆分数字是因为您想让用户单独编辑它们,如下所示:
如果那是你想要的,你不应该为每个数字单独设置 @State
属性。相反,weight
应该是 @Binding
并且每个数字应该有一个单独的可变 属性。
首先,扩展 Double
以允许您访问数字:
fileprivate extension Double {
var tens: Int {
get { sigFigs / 1000 }
set { replace(tens: newValue) }
}
var ones: Int {
get { (sigFigs / 100) % 10 }
set { replace(ones: newValue) }
}
var tenths: Int {
get { (sigFigs / 10) % 10 }
set { replace(tenths: newValue) }
}
var hundredths: Int {
get { sigFigs % 10 }
set { replace(hundredths: newValue) }
}
private mutating func replace(tens: Int? = nil, ones: Int? = nil, tenths: Int? = nil, hundredths: Int? = nil) {
self = Double(0
+ 1000 * (tens ?? self.tens)
+ 100 * (ones ?? self.ones)
+ 10 * (tenths ?? self.tenths)
+ (hundredths ?? self.hundredths)) / 100.0
}
private var sigFigs: Int {
return Int((self * 100).rounded(.toNearestOrEven))
}
}
然后,将 ContentDetail
的 weight
属性 更改为 @Binding
并去掉其他属性:
struct ContentDetail: View {
@Binding var weight: Double
var body: some View {
HStack {
DigitPicker(digitName: "tens", digit: $weight.tens)
DigitPicker(digitName: "ones", digit: $weight.ones)
DigitPicker(digitName: "tenths", digit: $weight.tenths)
DigitPicker(digitName: "hundredths", digit: $weight.hundredths)
}
}
}
struct DigitPicker: View {
var digitName: String
@Binding var digit: Int
var body: some View {
VStack {
Picker(selection: $digit, label: Text(digitName)) {
ForEach(0 ... 9) {
Text("\([=12=])").tag([=12=])
}
}.frame(width: 60, height: 110).clipped()
}
}
}
下面是在操场上测试它所需的其余代码,这就是我生成上面那张图片的方式:
import PlaygroundSupport
struct TestView: View {
@State var weight: Double = 35.48
var body: some View {
VStack(spacing: 0) {
Text("Weight: \(weight)")
ContentDetail(weight: $weight)
.padding()
}
}
}
let host = UIHostingController(rootView: TestView())
host.preferredContentSize = .init(width: 320, height: 240)
PlaygroundPage.current.liveView = host