Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift中,是否可以在运行时从字符串执行代码?_Ios_Swift_Closures_Plist - Fatal编程技术网

Ios 在Swift中,是否可以在运行时从字符串执行代码?

Ios 在Swift中,是否可以在运行时从字符串执行代码?,ios,swift,closures,plist,Ios,Swift,Closures,Plist,我有一个项目列表,其中包含与之关联的条件。我希望将此项目列表及其条件存储在plist中,而不是将其硬编码到.swift文件中 唯一的问题是需要一个与每个项关联的函数来检查条件。下面是它可能看起来像硬编码的: let myJobStep1 = JobStep(heading: "My Heading", description: "This is the description", warningText: "", condition_check: { () -> Bool in r

我有一个项目列表,其中包含与之关联的条件。我希望将此项目列表及其条件存储在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文件中的字符串中


谢谢

最接近的方法是
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
由于
n表达式
基于Objective-C和键值,因此存在一些限制:

  • 正在评估的对象必须从
    NSObject
    派生
  • 属性必须能够自动转换为
    任何对象
    ,因此我们存储的是int而不是颜色。请注意,通过使用派生属性,您可能会以稍微不同的方式处理此问题
  • 替换字典必须是
    [String:AnyObject]
    ,因此必须使用枚举原始值而不是枚举值本身

  • 这听起来像是你的工作

    Swift-
    映射
    过滤器
    、速记闭包等中的函数式编程结构是在命令式代码中表达数据之间关系的绝佳工具。但它们并不是看待这些问题的唯一方式

    特别是,能够将数据之间的关系表示为数据通常很有用:

    • 如果要从一个简单的文件表示加载一组数据模型对象,也可以对它们的关系进行编码

    • 如果您将数据关系编码为数据,则可以在运行时加载/更新/下载它们,而无需更改代码和发送新的应用程序二进制文件

    • 如果您处理的是后端数据库/web服务/RDBMS/ORM(CloudKit、核心数据等),那么您需要一种方式来表达过滤器、查询、排序顺序和关系等内容,这些内容可以传递到后端,让昂贵的大数据处理操作在那里进行

    这就是我们的目的。与过滤器/比较闭包不同,与谓词关联的基本逻辑可以是数据,而不是代码。因此,您可以有一个如下所示的数据源:

    [
        "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击败了我。这更像是一个“为什么”/高级答案,但his在一些方面有很好的细节,比如在枚举案例、数据文件内容和谓词格式之间设置映射。

    KVC不需要可变属性:
    class Foo:NSObject{let val=“Bar”};设f=Foo();f、 valueForKey(“val”)
    工作正常。(一些不适合注释的较长变体也是如此。)确实如此,出于某种原因,它最初对我不起作用,但这很可能是因为我从类型颜色开始的。感谢您提供完整的示例,以及演示如何使用枚举值。在你和@rickster的回答之间,这正是我所需要的。非常感谢。哇,回答得很好。非常感谢。我甚至不知道我要找的东西有一个特定的名字——NSPredicate。这很有帮助。您认为谓词可能包含枚举值吗?(即
    trayColor==trayColor.Blue
    trayColor==.Blue
    )?我想我可以试试看,然后找到答案……枚举是一个快速的东西,而NSPredicate是一个ObjC派生的API。围绕这一点有多种方法-@DavidBerry在他的回答中展示了一种方法。另一个选项是让类公开第二个(计算的)属性,该属性将枚举值表示为int或string或其他形式。