SwiftUI ForEEach协议的结果是 " 要求内容符合无障碍路标 "
原标题:SwiftUI ForEach of protocols results in "requirement that Content conform to AccessibilityRotorContent "
I m looking at iterating over an array of protocols and get them each to render a view. The protocol has a buildView function that returns any View, but calling this inside my view has the error:
Static method buildExpression requires that Content conform to AccessibilityRotorContent
Here s the code below, I don t really know what s going on and would greatly appreciate some help in debugging it.
import UIKit
import SwiftUI
import PlaygroundSupport
protocol ViewItem: AnyObject, Hashable, Identifiable {
var id: UUID { get }
func buildView() -> any View
}
class ViewOne: ViewItem {
let id: UUID = UUID()
func buildView() -> any View {
Text("View one")
}
static func == (lhs: ViewOne, rhs: ViewOne) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
class ViewTwo: ViewItem {
let id: UUID = UUID()
func buildView() -> any View {
Text("View two")
}
static func == (lhs: ViewTwo, rhs: ViewTwo) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
struct ContentView: View {
let viewItems: [any ViewItem]
var body: some View {
VStack {
ForEach(viewItems, id: .id) { viewItem in
viewItem.buildView() <------------------ ERROR HERE
}
}
}
}
问题回答
func buildView() -> any View
The code above is not allowed within body, with or without ForEach.
var body: some View {
VStack {
createAnyView() // ❌
createSomeView() // ✅
}
}
func createAnyView() -> any View {
Text("any view")
}
func createSomeView() -> some View {
Text("some view")
}
AFAIK, the body must contain some View or a type-erased AnyView. So, an approach is changing your protocol function to:
protocol ViewItem {
...
func buildView() -> AnyView
}
class ViewOne: ViewItem {
func buildView() -> AnyView {
AnyView(
Text("View one")
)
}
}
However, it has drawbacks such as unpredictable view state, animation, performance, etc... since SwiftUI doesn t even know what View it will be to optimize when it needs to re-render. You can check this out Demystify SwiftUI performance.
Thus, if I were you, I would go with some View solution:
protocol ViewItem {
...
associatedtype ContentView: View
func buildView() -> ContentView
}
Then I will wrap each type into a kind of builder, because passing directly ViewItem into a View will force the input param to any as mentioned in SE-0335.
enum Content: View, Identifiable {
case viewOne(ViewOne)
case viewTwo(ViewTwo)
var body: some View {
switch self {
case .viewOne(let viewOne):
viewOne.buildView()
case .viewTwo(let viewTwo):
viewTwo.buildView()
}
}
var id: ObjectIdentifier {
switch self {
case .viewOne(let viewOne):
return viewOne.id
case .viewTwo(let viewTwo):
return viewTwo.id
}
}
}
Finally, implement ContentView as normal:
struct ContentView: View {
var items: [Content]
var body: some View {
VStack {
ForEach(items) { item in
item.body
}
}
}
}
#Preview {
ContentView(items: [
.viewOne(.init()),
.viewTwo(.init())
])
}
Side note: If you have several return statements in each ViewItem, you might consider adding @ViewBuilder to your protocol to use the power of function builder.
相关问题
Button stops working after swiping up app in control center SwiftUI
My app is literally the default Xcode project with just a button that prints "Working" to the console when pressed. The button works when I first open the app on my phone. The button still ...
How to fix Sorry, something went wrong when trying to log in with Facebook on iOS using Firebase?
Facebook log in error:
"Sorry, something went wrong.
We are working on it and we ll get it fixed as soon as we can."
import FirebaseAuth
import FacebookLogin
private let ...
SwiftUI: Why does pass in @State value not changed in child view?
Both View1 and View2 get the parameter text from the parent ContentView. But in View1 uses @Binding while View2 uses @State. Clicking View1 button will change the text value. However, after clicking, ...
SwiftUI: How do I position a button x points above a sheet?
I am trying to recreate a Maps-style UI with a persistent bottom sheet and controls fixed above.
Apple Maps UI with controls above
☝️ Example here, the "Look Around" binoculars button and ...
BraintreeDropIn deprecated functions error
I m getting this error on the latest release of BraintreeDropIn, I really don t get it since based on the patch notes, this should ve been addressed already, I have already tried cleaning derived data,...
how to limit zoom level in map swift ui?
how to limit zoom level in map swift ui i have map and need to make zoom level limited
Map(coordinateRegion: $region,annotationItems: viewModel.nearbyGyms) { item in
...
Swift UI coloring url links inside of text blue while rest of text black
Hello I want to create a struct that returns Text, the text that it should return should detect wether a link is nested inside the text and if so open it when the text is tapped, I also want the ...
UIImageView - How to get the file name of the image assigned?
Is it possible to read the name of an UIImageView s UIImage
that s presently stored in the UIImageView?
I was hoping you could do something kind of like this, but haven t figured it out.
NSString *...