我有一个与其相关的条件列表。我想将这个项目列表及其条件存储在plist中,而不是将它们硬编码到.swift文件中。
唯一的问题是需要与每个项目相关联的功能来检查条件。这就是硬编码的样子:
let myJobStep1 = JobStep(heading: "My Heading", description: "This is the description", warningText: "", condition_check: { () -> Bool in
return (self.trayColor == .Blue) || (self.trayColor == .Red)
})
let myJobStep2 = JobStep(heading: "My Heading", description: "Another description", warningText: "", condition_check: { () -> Bool in
return (self.trayColor == .Green)
})
问题是如何封装检查条件的函数,该函数可以在plist文件中。
谢谢!
答案 0 :(得分:2)
你最接近的是NSPredicate
和/或NSExpression
,这使你有能力动态评估以字符串形式给出的表达式。
enum Colors : Int {
case Red = 1
case Green = 2
case Blue = 3
}
class Line : NSObject {
var lineColor : Int
init(lineColor:Colors) {
self.lineColor = lineColor.rawValue
}
}
let red = Line(lineColor: .Red)
let green = Line(lineColor: .Green)
let basic = NSPredicate(format: "self.lineColor == $Red")
let test = basic.predicateWithSubstitutionVariables(["Red":Colors.Red.rawValue])
test.evaluateWithObject(red) // true
test.evaluateWithObject(green) // false
由于NSExpression
基于Objective-C和Key Values,因此存在一些限制:
NSObject
。AnyObject
,因此我们存储的是int而不是Color。请注意,使用派生属性可能会有所不同。[String:AnyObject]
,因此您必须使用枚举原始值而不是枚举值本身。答案 1 :(得分:1)
这听起来像是predicates的工作!
Swift中的函数式编程构造 - map
,filter
,速记闭包等 - 是您在命令式代码中表达数据之间关系时的绝佳工具 。但它们并不是解决这些问题的唯一方法。
特别是,能够将数据之间的关系表示为数据通常很有用:
如果您从简单的文件表示中加载一堆数据模型对象,您也可以对它们之间的关系进行编码。
如果您将数据关系编码为数据,则可以在运行时加载/更新/下载它们,而不是更改代码并发送新的应用二进制文件。
如果您正在处理后端数据库/ Web服务/ RDBMS / ORM(CloudKit,核心数据等),您需要一种表达过滤器,查询,排序顺序和关系等方法的方法您可以传递到后端,并在那里进行大型昂贵的数据处理操作。
这是NSPredicate
(以及相关的NSSortDescriptor
)的用途。与过滤器/比较闭包不同,与谓词相关的基本逻辑可以是数据,而不是代码。因此,您可以拥有如下所示的数据源:
[
"heading": "My Heading",
"description": "This is the description",
"condition": "trayColor == \"Blue\" || trayColor == \"Red\""
]
然后,您可以从数据源创建谓词:
let predicate = NSPredicate(format: item.condition)
并使用它们来测试单个对象,过滤器集合等的条件:
predicate.evaluateWithObject(item)
(items as NSArray).filteredArrayUsingPredicate(predicate)
编辑: @DavidBerry打败了我。这更像是一个"为什么" /高级答案,但他有一些很好的细节,比如在枚举案例,数据文件内容和谓词格式之间建立映射。