Ama*_*nda 4 iphone ios swift swiftui
所以我在运行我设置的游戏应用程序时收到此错误:
\n当出现更多相同卡牌时的游戏屏幕图像(游戏中的所有卡牌都应该是唯一的)
\nForEach<Range<Int>, Int, ModifiedContent<_ConditionalContent<_ConditionalContent<_ConditionalContent<_ConditionalContent\n<ZStack<TupleView<(_ShapeView<Squiggle, ForegroundStyle>, \n_StrokedShape<Squiggle>)>>, ZStack<TupleView<(ModifiedContent<_StrokedShape<StripedRect>, \n_ClipEffect<Squiggle>>, _StrokedShape<Squiggle>)>>>, _StrokedShape<Squiggle>>, \n_ConditionalContent<_ConditionalContent<ZStack<TupleView<(_ShapeView<Capsule, ForegroundStyle>, _StrokedShape<Capsule>)>>, \nZStack<TupleView<(ModifiedContent<_StrokedShape<StripedRect>, _ClipEffect<Capsule>>, \n_StrokedShape<Capsule>)>>>, _StrokedShape<Capsule>>>, _ConditionalContent<_ConditionalContent<ZStack<TupleView<(_ShapeView<Diamond, \nForegroundStyle>, _StrokedShape<Diamond>)>>, ZStack<TupleView<(ModifiedContent<_StrokedShape<StripedRect>, _ClipEffect<Diamond>>, \n_StrokedShape<Diamond>)>>>, _StrokedShape<Diamond>>>,\n _FrameLayout>> count (2) != its initial count (1). `ForEach(_:content:)`\n should only be used for *constant* data. Instead conform data to `Identifiable` \nor use `ForEach(_:id:content:)` and provide an explicit `id`!\nRun Code Online (Sandbox Code Playgroud)\n视图本身下方的卡片模型似乎没有改变。除了卡片上的形状数量之外,所有内容都保持不变。因此,仅当底层模型正确匹配时,显示错误的卡片才会匹配,并且不会像视图中显示的那样匹配。
\n仅当我获得正确的设置并按“显示另外三张卡片”或当我显示的卡片多于可见卡片然后在屏幕上上下滚动时,才会出现该错误。
\n应用程序不会因错误而停止,但每张卡上的 numberOfShapes 会动态变化(如上面的屏幕截图所示)。(当我滚动到屏幕顶部然后滚动到底部时,这一点最为清晰,并且某些卡片上的形状数量每次都会发生变化)
\n所以我认为问题可能出在卡片视图中:
\nimport SwiftUI\n\nstruct CardView: View {\n \n var card: Model.Card\n \n var body: some View {\n GeometryReader { geometry in\n ZStack{\n let shape = RoundedRectangle(cornerRadius: 10)\n if !card.isMatched {\n shape.fill().foregroundColor(.white)\n shape.strokeBorder(lineWidth: 4).foregroundColor(card.isSelected ? .red : .blue)\n }\n \n VStack {\n Spacer(minLength: 0)\n //TODO: Error here?\n ForEach(0..<card.numberOfShapes.rawValue) { index in\n cardShape().frame(height: geometry.size.height/6)\n }\n Spacer(minLength: 0)\n }.padding()\n .foregroundColor(setColor())\n .aspectRatio(CGFloat(6.0/8.0), contentMode: .fit)\n .frame(width: geometry.size.width, height: geometry.size.height)\n }\n }\n }\n \n @ViewBuilder private func cardShape() -> some View {\n switch card.shape {\n case .squiglle: shapeFill(shape: Squiggle())\n case .roundedRectangle: shapeFill(shape: Capsule())\n case .diamond: shapeFill(shape: Diamond())\n }\n }\n \n private func setColor() -> Color {\n switch card.color {\n case .pink: return Color.pink\n case .orange: return Color.orange\n case .green: return Color.green\n }\n }\n \n @ViewBuilder private func shapeFill<setShape>(shape: setShape) -> some View\n //TODO: se l\xc3\xb8sning, brug rawvalues for cleanness\n where setShape: Shape {\n switch card.fill {\n case .fill: shape.fillAndBorder()\n case .stripes: shape.stripe()\n case .none: shape.stroke(lineWidth: 2)\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n卡片视图以灵活的网格布局显示:
\nimport SwiftUI\n\nstruct AspectVGrid<Item, ItemView>: View where ItemView: View, Item: Identifiable {\n var items: [Item]\n var aspectRatio: CGFloat\n var content: (Item) -> ItemView\n let maxColumnCount = 6\n \n init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) {\n self.items = items\n self.aspectRatio = aspectRatio\n self.content = content\n }\n \n var body: some View {\n GeometryReader { geometry in\n VStack {\n let width: CGFloat = widthThatFits(itemCount: items.count, in: geometry.size, itemAspectRatio: aspectRatio)\n ScrollView{\n LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) {\n ForEach(items) { item in\n content(item).aspectRatio(aspectRatio, contentMode: .fit)\n }\n Spacer(minLength: 0)\n }\n }\n }\n }\n }\n \n private func adaptiveGridItem(width: CGFloat) -> GridItem {\n var gridItem = GridItem(.adaptive(minimum: width))\n gridItem.spacing = 0\n return gridItem\n }\nRun Code Online (Sandbox Code Playgroud)\n看法:
\nimport SwiftUI\n\nstruct SetGameView: View {\n @StateObject var game: ViewModel\n \n var body: some View {\n VStack{\n HStack(alignment: .bottom){\n Text("Set Game")\n .font(.largeTitle)\n }\n AspectVGrid(items: game.cards, aspectRatio: 2/3) { card in\n CardView(card: card)\n .padding(4)\n .onTapGesture {\n game.choose(card)\n \n }\n }.foregroundColor(.blue)\n .padding(.horizontal)\n Button("show 3 more cards"){\n game.showThreeMoreCardsFromDeck()\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n非常感谢任何解决此问题的帮助。我已经在这上面花了很多时间了。
\nrob*_*off 13
你的问题在这里:
\n\n\nRun Code Online (Sandbox Code Playgroud)\nForEach(0..<card.numberOfShapes.rawValue) { index in\n cardShape().frame(height: geometry.size.height/6)\n}\n
该ForEach初始化程序的第一个参数是Range<Int>. 文档说(强调):
\n\n该实例仅读取所提供数据的初始值,并且不需要识别更新之间的视图。要在动态范围内按需计算视图,请使用
\nForEach/init(_:id:content:)。
因为它只读取\xe2\x80\x9c提供的数据\xe2\x80\x9d的初始值,所以只有当 是Range<Int>常量时才可以安全使用。如果改变范围,效果是不可预测的。因此,从 Xcode 13 开始,如果您传递非常量范围,编译器会发出警告。
现在,也许你的范围 ( 0..<card.numberOfShapes.rawValue) 确实是恒定的。但编译器不知道这一点。(根据您的错误,它不是一个恒定的范围。)
您可以通过切换到带有参数的初始化器来避免警告id::
ForEach(0..<card.numberOfShapes.rawValue, id: \\.self) { index in\n // ^^^^^^^^^^^^^\n // add this\n cardShape().frame(height: geometry.size.height/6)\n}\nRun Code Online (Sandbox Code Playgroud)\n