Swift中GKRuleSystem与NSPredicate使用结果异常,求正确用法
Swift中GKRuleSystem规则判断问题修正
问题现象
用Swift实现的GKRuleSystem规则判断逻辑,无论distanceToPlayer取何值,hunt事实的判断结果始终为True,不符合预期;而对应的Objective-C版本逻辑正常——当玩家距离近时会撤回hunt事实,结果为False。
核心问题
对比两段代码可以发现,Swift版本中玩家近距离规则的类型错误:
- Objective-C代码中,近距离规则使用
retractingFact:@"hunt"(撤回事实) - Swift代码中,错误地使用了
assertingFact: assertingFactKey(断言事实)
这导致无论玩家远近,两条规则都在断言hunt事实,最终grade始终大于0,结果永远为True。
修正后的Swift代码
let assertingFactKey = "hunt" let ruleSystem = GKRuleSystem() // 玩家远距离时,断言hunt事实 let playerFar = NSPredicate(format: "$distanceToPlayer.floatValue >= 10.0") ruleSystem.add(GKRule(predicate: playerFar, assertingFact: assertingFactKey, grade: 1.0)) // 玩家近距离时,撤回hunt事实 let playerNear = NSPredicate(format: "$distanceToPlayer.floatValue < 10.0") ruleSystem.add(GKRule(predicate: playerNear, retractingFact: assertingFactKey, grade: 1.0)) for i in 1...30 { ruleSystem.state["distanceToPlayer"] = NSNumber(value: i) // 存入NSNumber,匹配predicate的floatValue调用 ruleSystem.reset() ruleSystem.evaluate() let result = ruleSystem.grade(forFact: assertingFactKey) > 0.0 print(result ? "**True : \(i)" : "**False") }
额外说明
assertingFactKey无需转成NSString,Swift原生String可以直接与GKRuleSystem兼容。- 向
ruleSystem.state存入NSNumber而非直接存Int,能更稳妥地匹配谓词中的.floatValue调用,避免类型转换问题。 - 修正后运行结果与Objective-C版本一致:当
i < 10时输出**False,i >=10时输出**True : [i]。
内容的提问来源于stack exchange,提问作者Zou
相关产品推荐
相关产品推荐

