NSPredicate 按名称传递“多个”参数[在 Swift 中]

Posted

技术标签:

【中文标题】NSPredicate 按名称传递“多个”参数[在 Swift 中]【英文标题】:NSPredicate pass "multiple" parameters by name [in Swift] 【发布时间】:2016-07-01 02:58:46 【问题描述】:

是否可以通过命名而不是%@来将多个参数传递给NSPredicate

例如,我有一个directly-passed 参数meyou

public static func ConversationByUserId( userId : String ) -> [Message] 

    // Either Created By me and sent to you.
    // Or, created by you and sent to me


    let me = UserRepo.GetLoggedInUser()?.id

    var format = "( createdBy == '" + me! + "'  && createdTo == '"  +  userId + "') "
    format += " || ( createdBy == '" + userId + "'  && createdTo == '" + me! + "') "


    print(format)
    //prints: ( createdBy == '1'  && createdTo == '5')  || ( createdBy == '5'  && createdTo == '1')


    let predicate = NSPredicate(format:  format)

    return Filter(predicate);



注意:Filter(predicate) 执行操作并返回结果。到现在为止还挺好。我得到了预期的结果。但我猜这可能会出现 SQL 攻击之类的问题。

我可以像下面这样做吗:如果可以,怎么做?

  var format = "( createdBy == @me  && createdTo == @you ) "
  format += " || ( createdBy == @you  && createdTo == @me ) "


 let predicate = NSPredicate(format:  format, [ "me" : me, "you" : you ])

目前我取得的成就是:

    format = "( createdBy == %@  && createdTo == %@ ) "
    format += " || ( createdBy == %@  && createdTo == %@ ) "


    let predicate = NSPredicate(format:  format, me!, you, me!, you)

【问题讨论】:

这个答案和其他人谈论使用 NSComparisonPredicate 防止 SQL 注入:***.com/questions/3076894/… @Moshe,对我来说没有意义。如果您知道,请迅速发布答案? 【参考方案1】:

您可以使用 NSPredicate 的predicateWithSubstitutionVariables(参见Apple Docs)。像往常一样创建谓词,使用“$variable”代替您要替换的值:

var format = "( createdBy == $me  && createdTo == $you ) "
format += " || ( createdBy == $you  && createdTo == $me ) "
let predicate = NSPredicate(format:  format)

然后创建一个包含变量名和要传递的值的字典:

let subVars = ["me" : me!, "you" : you!]

最后用你的值替换变量名来创建谓词:

let finalPredicate = predicate.predicateWithSubstitutionVariables(subVars)

【讨论】:

这对于复杂的提取来说是超级骗子,优雅且易于编写/阅读和理解,甚至几个月后。非常感谢!【参考方案2】:

注意:您不会在 ios 应用程序中遭受 SQL 注入攻击。除非您让用户输入 SQL,然后将该 SQL 发送到某处的服务器,否则不存在 SQL 注入攻击的风险。

Core Data 和 NSPredicate 不能这样工作。

话虽如此;您可以使用NSExpression 实例并从NSExpression 部分的组合中构建一个NSComparisonPredicate

let me = 1123 //Example value

let test = [["createdBy":1124,"name":"Fred"],["createdBy":1123,"name":"Jane"]] as NSArray

let lhs = NSExpression(forKeyPath: "createdBy")
let rhs = NSExpression(forConstantValue: me)

let predicate = NSComparisonPredicate(leftExpression: lhs, rightExpression: rhs, modifier: NSComparisonPredicateModifier.DirectPredicateModifier, type: NSPredicateOperatorType.EqualToPredicateOperatorType, options: [])

let results = test.filteredArrayUsingPredicate(predicate)
print("Results: \(results)")

NSComparisonPredicateNSCompoundPredicate 结合使用,您可以构建任何您想要的东西。

【讨论】:

以上是关于NSPredicate 按名称传递“多个”参数[在 Swift 中]的主要内容,如果未能解决你的问题,请参考以下文章

如何在不同的数据上使用 NSPredicate 和 NSPredicateEditor(多个谓词?)

Core Data NSPredicate 按数组中的项目过滤项目集

NSPredicate 过滤关系

按名称传递参数

采用核心数据,按多个标准过滤。我想要 NSPredicate 吗?

[Scala函数特性系列]——按名称传递参数