SwiftUI循环生成10张不同卡片却全部显示重复问题求解
问题原因分析
- 存储逻辑错误:你在Card类中只声明了单个
result字符串属性,init方法里的10次循环每次都会覆盖上一次的生成结果,最终result只会保留最后一次生成的随机字符串,没有存储10个不同的卡片标识。 - 视图遍历逻辑错误:EasyModeView的ForEach循环10次时,每次都读取同一个
cardModel.result值,自然所有卡片展示的都是同一张图片。 - 语法错误:随机取值的两行代码中,
Int(arc4random() % 4后缺少右闭合括号,运行会直接报错。 - 可观察对象规则不符合:ObservableObject类型的属性如果需要触发视图刷新,需要添加
@Published修饰符,否则数据变化无法同步到视图。
修复后的完整代码
首先修改Card类,用数组存储10个卡片标识:
import Foundation class Card: Identifiable, ObservableObject { var id = UUID() // 用数组存储10个不同的卡片字符串,添加@Published支持数据变化通知 @Published var resultList: [String] = [] init() { // 提前定义常量避免循环内重复创建 let suitList = ["D","K","B","S"] let numList = ["1","2","3","4"] for _ in 1...10 { // 补全闭合括号修复语法错误 let suit = suitList[Int(arc4random() % 4)] let numStr = numList[Int(arc4random() % 4)] // 将生成的标识添加到数组,而非覆盖单个变量 resultList.append(suit + numStr) } } }
再修改视图层逻辑,直接遍历生成好的卡片数组:
import SwiftUI struct EasyModeView: View { @ObservedObject var cardModel: Card var body : some View { HStack { // 遍历卡片数组获取每个卡片的独立标识 ForEach(cardModel.resultList, id: \.self) { cardStr in Button { } label: { Image(cardStr) .resizable() .scaledToFit() } } } } }
可选优化方案
如果需要保证10张卡片完全不重复,可在生成标识时增加重复校验逻辑:
while resultList.count < 10 { let suit = suitList[Int.random(in: 0..<3)] let numStr = numList[Int.random(in: 0..<3)] let tempStr = suit + numStr if !resultList.contains(tempStr) { resultList.append(tempStr) } }
该方案使用Swift原生的random(in:)方法代替arc4random(),不需要额外类型转换,语法更简洁安全。
内容的提问来源于stack exchange,提问作者Frane Vučemilović -Vranjić
相关产品推荐
相关产品推荐

