You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift/iOS类中基于Core Data表实现非硬编码业务规则的方法咨询

在Swift/iOS中基于Core Data规则表实现业务决策

核心问题拆解

要替代硬编码的if/then逻辑,核心需要解决两个问题:

  1. 解析字符串形式的属性路径(如joints.arm.wrist.left.y),获取类中对应变量的实际值
  2. 根据规则表的条件执行比较,再通过字符串路径设置类属性(如self.elevated)

实现步骤

1. 定义Core Data规则实体

在Core Data中创建Rule实体,包含以下属性:

  • leftExpression: String(左属性路径,如joints.arm.wrist.left.y)
  • condition: String(比较运算符,如>、<、==)
  • rightExpression: String(右属性路径,如joints.shoulder.left.y)
  • resultPath: String(目标属性路径,如elevated)
  • resultValue: String(目标属性值,如true)

2. 实现动态属性访问工具

基于Swift Runtime实现通用的属性路径解析、取值和赋值方法(需确保业务类继承自NSObject):

import ObjectiveC

extension NSObject {
    // 根据字符串路径获取属性值
    func value(forPath path: String) -> Any? {
        let components = path.components(separatedBy: ".")
        var currentValue: Any? = self
        
        for component in components {
            guard let obj = currentValue as? NSObject else { return nil }
            currentValue = obj.value(forKey: component)
        }
        return currentValue
    }
    
    // 根据字符串路径设置属性值
    func setValue(_ rawValue: String?, forPath path: String) {
        let components = path.components(separatedBy: ".")
        guard components.count > 0, let rawValue else { return }
        
        var currentObj: NSObject = self
        // 遍历到目标属性的父对象
        for i in 0..<components.count - 1 {
            guard let nextObj = currentObj.value(forKey: components[i]) as? NSObject else { return }
            currentObj = nextObj
        }
        
        let targetKey = components.last!
        // 处理常见类型转换,可根据需求扩展
        if let boolVal = Bool(rawValue) {
            currentObj.setValue(boolVal, forKey: targetKey)
        } else if let floatVal = Float(rawValue) {
            currentObj.setValue(floatVal, forKey: targetKey)
        } else {
            currentObj.setValue(rawValue, forKey: targetKey)
        }
    }
}

3. 规则评估逻辑实现

在业务类中编写规则评估方法,读取Core Data中的规则并执行判断:

class MotionMonitor: NSObject {
    // 业务类变量(示例结构,需与实际代码对齐)
    var joints = Joints()
    var elevated = false
    
    // 模拟关节数据结构,需继承NSObject以支持Runtime访问
    class Joints: NSObject {
        var shoulder = BodyPart()
        var arm = ArmPart()
    }
    
    class BodyPart: NSObject {
        var left = JointCoordinate()
    }
    
    class ArmPart: NSObject {
        var wrist = BodyPart()
    }
    
    class JointCoordinate: NSObject {
        var y: CGFloat = 0.0
    }
    
    // 评估单条规则
    func evaluateRule(_ rule: Rule) {
        // 获取左右表达式的数值
        guard let leftVal = self.value(forPath: rule.leftExpression) as? CGFloat,
              let rightVal = self.value(forPath: rule.rightExpression) as? CGFloat else {
            return
        }
        
        // 判断条件是否满足
        var conditionMet = false
        switch rule.condition {
        case ">": conditionMet = leftVal > rightVal
        case "<": conditionMet = leftVal < rightVal
        case "==": conditionMet = leftVal == rightVal
        // 可扩展支持>=、<=等运算符
        default: return
        }
        
        // 满足条件则执行赋值操作
        if conditionMet {
            self.setValue(rule.resultValue, forPath: rule.resultPath)
            print("warning")
        }
    }
    
    // 批量评估所有Core Data中的规则
    func evaluateAllRules() {
        let fetchRequest: NSFetchRequest<Rule> = Rule.fetchRequest()
        guard let rules = try? CoreDataStack.shared.context.fetch(fetchRequest) else { return }
        rules.forEach(evaluateRule)
    }
}

4. 关键注意事项

  • 所有需要动态访问的类必须继承自NSObject,否则无法使用value(forKey:)和setValue(_:forKey:)方法
  • Core Data中存储的属性路径必须与业务类的属性名严格一致,避免拼写错误
  • 类型转换逻辑需根据业务需求扩展,比如支持整数、字符串等更多类型
  • 若需要支持复杂表达式(如包含计算),可考虑引入轻量表达式解析库,但简单属性比较场景下上述方案足够

内容的提问来源于stack exchange,提问作者iOScoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 03:00:08