Swift中@State属性随机更新字符串时如何避免重复选取
Swift 无重复随机更新资源文件名实现方案
核心思路
不需要每次随机生成后缀后做重复校验,直接提前把所有合法的文件名组合全量生成,打乱顺序后作为待选队列,按顺序依次取值即可,既可以完全避免重复,也能在所有组合取完后自动停止更新,逻辑最简、性能开销最低。
实现代码
import SwiftUI struct RelevantWordView: View { @State private var relevantWord = "bird" // 预生成所有合法组合并随机打乱 @State private var candidateQueue: [String] = { let numberOptions = 1...5 let letterOptions = ["a", "b", "c", "d"] var allValidWords = [String]() for num in numberOptions { for char in letterOptions { allValidWords.append("bird\(num)\(char)") } } return allValidWords.shuffled() }() // 记录当前取到队列的位置 @State private var pointer = 0 var body: some View { VStack(spacing: 30) { Text(relevantWord) .font(.title) Button("切换词条") { // 队列已取完时直接返回,不更新值 guard pointer < candidateQueue.count else { return } // 取当前位置的不重复随机值 relevantWord = candidateQueue[pointer] // 指针后移 pointer += 1 } // 资源耗尽时禁用按钮,避免无效点击 .disabled(pointer >= candidateQueue.count) } .padding() } }
方案说明
- 示例中数字可选范围是1-5共5个值,字母可选范围是a-d共4个值,总共有20种合法组合,预生成逻辑会覆盖所有可能的文件名,不会出现漏取
- 打乱队列的操作在视图初始化时仅执行一次,后续点击按钮不需要做任何随机计算、重复校验,性能远高于每次随机生成后比对已用值的方案
- 如果需要调整可选的数字、字母范围,只需要修改
numberOptions和letterOptions的取值即可,不需要调整其他逻辑 - 如果需要页面首次加载就展示第一个随机词条,只需要在
.onAppear修饰符中执行一次按钮内的赋值逻辑,同时把pointer初始值设为1即可
如果后续资源文件会扩充,不需要修改后缀拼接规则,只需要把预生成组合的逻辑替换为从资源目录读取所有符合命名规则的文件名即可,整体逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Pacha
相关产品推荐
相关产品推荐

