NSPredicateEditor 与核心数据关系
NSPredicateEditor with Core Data relationship
我有一个包含两个实体的核心数据数据模型,文档和字段:
文档:
- 字段[对多关系]
字段:
- 姓名
- 字段文本
- 字段日期
- 字段编号
- 文件 [对一种关系]
我正在尝试设置 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 子类化吗?如果是的话,应该怎么做?在此先感谢您的帮助。
子类 NSPredicateEditorRowTemplate
并覆盖 predicateWithSubpredicates
以将谓词 "FIELDNAME CONTAINS <entered text>"
转换为谓词 "name == FIELDNAME && fieldText CONTAINS <entered text>"
.
我有一个包含两个实体的核心数据数据模型,文档和字段:
文档:
- 字段[对多关系]
字段:
- 姓名
- 字段文本
- 字段日期
- 字段编号
- 文件 [对一种关系]
我正在尝试设置 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 子类化吗?如果是的话,应该怎么做?在此先感谢您的帮助。
子类 NSPredicateEditorRowTemplate
并覆盖 predicateWithSubpredicates
以将谓词 "FIELDNAME CONTAINS <entered text>"
转换为谓词 "name == FIELDNAME && fieldText CONTAINS <entered text>"
.