问题
I've been trying to make an app for iOS 13 using Swift UI but I keep getting this weird error: "ambiguous reference to member 'buildBlock()'".
No matter what I do the error won't go away.
I tried commenting of sections of code at a time to see which part might have been causing the issue, but the only thing that ever worked was commenting out the entire view.
I've tried cleaning my build folder and deleting derived data. I also tried restarting my computer and Xcode multiple times, nothing has fixed it.
I'm pretty sure that this is just an Xcode bug, but there must be away around it, I'd really appreciate if anyone could tell me what that is.
var body: some View {
GeometryReader { geometry in {
VStack {
Button (action: self.editProfilePicture) {
Image(ImageNames.AccountIconImageName, bundle: Bundle.main)
.resizable()
.frame(width: geometry.size.width / SizeConstants.AccountIconSizeDiviser, height: geometry.size.width / SizeConstants.AccountIconSizeDiviser)
.padding()
.background(ColorConstants.VeryLightGrayColor)
.clipShape(Circle())
}
.accentColor(.white)
.padding(.bottom, LargePadding)
ScrollView (showsVerticalIndicator: false) {
let const: Length? = geometry.size.width - SizeConstants.FullNameTextFieldWidthReduction
TextBox(textBinding: self.$fullName, placeHolder: Text(Strings.FullNameString), editChanged: self.fullNameChanged)/*.padding(.bottom, SmallPadding)*/.frame(width: const)
TextBox(textBinding: self.$username, placeHolder: Text(Strings.UsernameString), editChanged: self.usernameChanged)//.padding(.bottom)
Text(verbatim: Strings.ChooseIdType).font(.footnote).color(.gray)
TextBox(textBinding: self.$phoneNumber, placeHolder: Text(Strings.PhoneNumberString), editChanged: self.phoneNumberChanged)//.padding(.bottom, SmallPadding)
TextBox(textBinding: self.$emailAddress, placeHolder: Text(Strings.EmailAddressString), editChanged: self.emailAddressChanged)//.padding(.bottom)
Spacer(minLength: PaddingConstants.FirstSignupSpacerMinSize)
TextBox(textBinding: self.$password, placeHolder: Text(Strings.PasswordFieldPlaceHolder), editChanged: self.signupPasswordChanged)//.padding(.bottom, SmallPadding)
TextBox(textBinding: self.$confirmPassword, placeHolder: Text(Strings.ConfirmPasswordString), editChanged: self.confirmPasswordChanged)//.padding(.bottom)
Spacer(minLength: PaddingConstants.SecondSignupSpacerMinSize)
Button (action: self.signup) {
Text(Strings.CreateAccountString).color(.white).font(Font.system(size: SizeConstants.LoginButtonFontSize))
}
.padding(EdgeInsets(top: PaddingConstants.CreatAccountButtonVerticalPadding,
leading: PaddingConstants.CreateAccountButtonSidePadding,
bottom: PaddingConstants.CreatAccountButtonVerticalPadding,
trailing: PaddingConstants.CreateAccountButtonSidePadding))
.background(LeznoBlue)
.clipShape(RoundedRectangle(cornerRadius: SmallCornerRadius))
Spacer(minLength: PaddingConstants.ThirdSignupSpacerMinSize)
Text(Strings.AgreementString)
HStack {
Button (action: {}) {
Text(Strings.TermsString)
}
Text(Strings.AndString)
Button (action: {}) {
Text(Strings.PrivacyString)
}
}
}
}
.padding()
}
}
Screenshot of the error
EDIT:
So as it turns out I forgot that you can only have a maximum of 10 view in a view builder closure, and I had more than that. Simply putting them into groups to reduce the view count solved the error.
The error that Xcode displays is just very misleading as it turns out.
Thanks to Hamish for pointing it out
回答1:
As @Hamish originally mentioned in comments, ViewBuilder's can not exceeding over 10 subview limit! So you should group items in smaller pieces and try to add them group by group.
So instead of something like this: (This is a working example based on your original code, not exactly the same)
struct ContentView : View {
@State var firstName: String = ""
@State var lastName: String = ""
@State var phoneNumber: String = ""
@State var emailAddress: String = ""
@State var password: String = ""
@State var confirmPassword: String = ""
var body: some View {
ScrollView (showsVerticalIndicator: false) {
TextField($firstName, placeholder: Text("First Name"))
TextField($lastName, placeholder: Text("Last Name"))
Spacer()
TextField($phoneNumber, placeholder: Text("Phone Number"))
TextField($emailAddress, placeholder: Text("Email Address"))
Spacer()
TextField($password, placeholder: Text("Password"))
TextField($confirmPassword, placeholder: Text("Confirm Password"))
// ...
}
.padding()
}
}
Consider breaking it into meaningful smaller groups like this:
struct NameSectionView : View {
@State var firstName: String
@State var lastName: String
var body: some View {
Group {
TextField($firstName, placeholder: Text("First Name"))
TextField($lastName, placeholder: Text("Last Name"))
}
}
}
struct ContactSectionView : View {
@State var phoneNumber: String
@State var emailAddress: String
var body: some View {
Group {
TextField($phoneNumber, placeholder: Text("Phone Number"))
TextField($emailAddress, placeholder: Text("Email Address"))
}
}
}
struct PasswordSectionView : View {
@State var password: String
@State var confirmPassword: String
var body: some View {
Group {
TextField($password, placeholder: Text("Password"))
TextField($confirmPassword, placeholder: Text("Confirm Password"))
}
}
}
and use them like this:
struct ContentView : View {
@State var firstName: String = ""
@State var lastName: String = ""
@State var phoneNumber: String = ""
@State var emailAddress: String = ""
@State var password: String = ""
@State var confirmPassword: String = ""
var body: some View {
ScrollView (showsVerticalIndicator: false) {
NameSectionView(firstName: firstName, lastName: lastName)
Spacer()
ContactSectionView(phoneNumber: phoneNumber, emailAddress: emailAddress)
Spacer()
PasswordSectionView(password: password, confirmPassword: confirmPassword)
// ...
}
.padding()
}
}
Also this is more reusable if you ever want to use any of these somewhere else.
来源:https://stackoverflow.com/questions/56655454/ambiguous-reference-to-member-buildblock