具有核心数据关系的NSPredicateEditor

时间:2016-08-03 23:30:04

标签: swift core-data subquery nspredicateeditor nspredicateeditorrow

我有一个核心数据数据模型,包含两个实体,Document和Field:

  • 文件:

    • fields [to many relationship]
  • 字段:

    • 名称
    • fieldText
    • fieldDate
    • fieldNumber
    • 文件[对一个关系]

我正在尝试设置NSPredicateEditor,以允许某人根据某些字段的内容过滤文档。我像这样手动构建谓词编辑器:

func updatePredicateEditor() {
    print("updatePredicateEditor")

    let sortDescriptor = NSSortDescriptor(key: "orderIndex", ascending: true)
    fieldsArrayController.sortDescriptors = [sortDescriptor]
    let fields = fieldsArrayController.arrangedObjects as! [Field]

    var keyPathsStringArray = [NSExpression]()
    var stringFieldNames = [String]()
    var keyPathsDateArray = [NSExpression]()
    var dateFieldNames = [String]()
    var keyPathsNumberArray = [NSExpression]()
    var numberFieldNames = [String]()

    for i in 0..<fields.count {
        let currentField = fields[i] 

        switch currentField.type! {
        case "Text":
            keyPathsStringArray.append(NSExpression(forKeyPath: "fieldText"))
            stringFieldNames.append(currentField.name!)
        case "Date":
            keyPathsDateArray.append(NSExpression(forKeyPath: "fieldDate"))
            dateFieldNames.append(currentField.name!)
        case "Number":
            keyPathsNumberArray.append(NSExpression(forKeyPath: "fieldNumber"))
            numberFieldNames.append(currentField.name!)
        default:
            print("error on field type")
        }
    }

    let stringOperators = [NSNumber(unsignedInteger: NSPredicateOperatorType.ContainsPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.EqualToPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.NotEqualToPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.BeginsWithPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.EndsWithPredicateOperatorType.rawValue)]

    let numberOperators = [NSNumber(unsignedInteger: NSPredicateOperatorType.EqualToPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.NotEqualToPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.LessThanPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.GreaterThanPredicateOperatorType.rawValue),
                           NSNumber(unsignedInteger: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType.rawValue)]


    let dateOperators = [NSNumber(unsignedInteger: NSPredicateOperatorType.EqualToPredicateOperatorType.rawValue),
                         NSNumber(unsignedInteger: NSPredicateOperatorType.NotEqualToPredicateOperatorType.rawValue),
                         NSNumber(unsignedInteger: NSPredicateOperatorType.LessThanPredicateOperatorType.rawValue),
                         NSNumber(unsignedInteger: NSPredicateOperatorType.LessThanOrEqualToPredicateOperatorType.rawValue),
                         NSNumber(unsignedInteger: NSPredicateOperatorType.GreaterThanPredicateOperatorType.rawValue),
                         NSNumber(unsignedInteger: NSPredicateOperatorType.GreaterThanOrEqualToPredicateOperatorType.rawValue)]

    var rowTemplatesTemp = [NSPredicateEditorRowTemplate]() // this is a temp array to hold the different popupbuttons

    // add a template for Strings

    let leftExpressionStringButton : NSPopUpButton

    if keyPathsStringArray.count == 0 {
        print("There aren't any text fields in NSPredicateEditor")
    }
    else {
        let stringTemplate = NSPredicateEditorRowTemplate(leftExpressions: keyPathsStringArray,
                                                                                         rightExpressionAttributeType: NSAttributeType.StringAttributeType,
                                                                                         modifier: NSComparisonPredicateModifier.DirectPredicateModifier,
                                                                                         operators: stringOperators,
                                                                                         options: (Int(NSComparisonPredicateOptions.CaseInsensitivePredicateOption.rawValue) |
                                                                                            Int(NSComparisonPredicateOptions.DiacriticInsensitivePredicateOption.rawValue)))

        leftExpressionStringButton = stringTemplate.templateViews[0] as! NSPopUpButton

        let stringButtonArray = leftExpressionStringButton.itemTitles

        for i in 0..<stringButtonArray.count {
            (leftExpressionStringButton.itemAtIndex(i)! as NSMenuItem).title = stringFieldNames[i] // set button menu names
        }

        rowTemplatesTemp.append(stringTemplate)
    }

    // add another template for Numbers...

    let leftExpressionNumberButton : NSPopUpButton

    if keyPathsNumberArray.count == 0 {
        print("There aren't any number fields in NSPredicateEditor")
    }
    else {
        let numberTemplate = NSPredicateEditorRowTemplate(leftExpressions: keyPathsNumberArray,
                                                                                         rightExpressionAttributeType: NSAttributeType.Integer32AttributeType,
                                                                                         modifier: NSComparisonPredicateModifier.DirectPredicateModifier,
                                                                                         operators: numberOperators,
                                                                                         options: 0)

        leftExpressionNumberButton = numberTemplate.templateViews[0] as! NSPopUpButton

        let numberButtonArray = leftExpressionNumberButton.itemTitles

        for i in 0..<numberButtonArray.count {
            (leftExpressionNumberButton.itemAtIndex(i)! as NSMenuItem).title = numberFieldNames[i] // set button menu names
        }

        rowTemplatesTemp.append(numberTemplate)
    }

    // add another template for Dates...

    let leftExpressionDateButton : NSPopUpButton

    if keyPathsDateArray.count == 0 {
        print("There aren't any date fields in NSPredicateEditor")
    }
    else {
        let dateTemplate = NSPredicateEditorRowTemplate(leftExpressions: keyPathsDateArray,
                                                        rightExpressionAttributeType: NSAttributeType.DateAttributeType,
                                                        modifier: NSComparisonPredicateModifier.DirectPredicateModifier,
                                                        operators: dateOperators,
                                                        options: 0)


        leftExpressionDateButton = dateTemplate.templateViews[0] as! NSPopUpButton

        let dateButtonArray = leftExpressionDateButton.itemTitles

        for i in 0..<dateButtonArray.count {
            (leftExpressionDateButton.itemAtIndex(i)! as NSMenuItem).title = dateFieldNames[i] // set button menu names
        }

        rowTemplatesTemp.append(dateTemplate)
    }

    // create the any, all or none thing...
    let compoundTypes = [NSNumber.init(unsignedInteger: NSCompoundPredicateType.OrPredicateType.rawValue),
                         NSNumber.init(unsignedInteger: NSCompoundPredicateType.AndPredicateType.rawValue),
                         NSNumber.init(unsignedInteger: NSCompoundPredicateType.NotPredicateType.rawValue)]

    // add the compoundtypes
    let compoundTemplate = NSPredicateEditorRowTemplate(compoundTypes: compoundTypes)
    rowTemplatesTemp.append(compoundTemplate)

    print("setting row templates \(rowTemplatesTemp)")

    predicateEditor.rowTemplates = rowTemplatesTemp

    predicateEditor.addRow(self)

}

问题是NSPredicateEditor不允许带有NSSubqueryExpressionType的NSExpressions,所以我不能将子查询作为我的左表达式。我需要NSPredicateEditorRowTemplate包含字段名称和属性路径(fieldText,fieldDate或fieldNumber),以便一行中的最终谓词如下所示:

name == FIELDNAME && fieldText CONTAINS "<entered text>"

有关如何执行此操作的任何建议吗?我应该继承NSPredicateEditorRowTemplate,如果是这样的话怎么样?在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

子类NSPredicateEditorRowTemplate并覆盖predicateWithSubpredicates以将谓词"FIELDNAME CONTAINS <entered text>"转换为谓词"name == FIELDNAME && fieldText CONTAINS <entered text>"