0

有没有人想出一个使用 NSPredicateEditor 按一天过滤数据( CoreData )的解决方案?这个想法是让用户最方便。标准解决方案是为 date 定义 2 个标准:

  1. 一个代表 >= 一天的开始
  2. <=一天结束的另一个。

一个 EditorRowTemplate 应该看起来像:

  • 左表达式 = aDate(核心数据实体的属性)

  • 右表达式 = 日期

在此处输入图像描述

然后,应用程序应该将谓词转换为有点像:

"aDate >= '3.5.20210 00:00:00' AND aDate <= '3.5.20210 23:59:59'".

当然,它应该取用户在行模板中输入的日期的值。

我想,闭包可能是一种方式。可以这么说,以编程方式创建 NSPredicate。但是如何在 NSExpression 中使用它并从输入中获取日期?

所需的行模板应如下所示:

在此处输入图像描述

4

2 回答 2

1

行模板可以将谓词转换为predicate(withSubpredicates:),无需其他覆盖。在 IB 中,正确的表达式是日期。

override func predicate(withSubpredicates subpredicates: [NSPredicate]?) -> NSPredicate {
    // call super to get the predicate, for example aDate == '3.5.20210 14:03:53'
    let predicate = super.predicate(withSubpredicates: subpredicates)
    // convert the predicate to aDate >= '3.5.2021 00:00:00' AND aDate < '4.5.2021 00:00:00'
    var newPredicate = predicate
    if let comparisonPredicate = predicate as? NSComparisonPredicate,
        let predicateDate = comparisonPredicate.rightExpression.constantValue as? Date {
        let keyPath = comparisonPredicate.leftExpression.keyPath
        var components = Calendar.current.dateComponents([.year, .month, .day], from: predicateDate)
        components.hour = 0
        components.minute = 0
        components.second = 0
        components.calendar = NSCalendar.current
        switch comparisonPredicate.predicateOperatorType {
            case .lessThan:
                // aDate < '3.5.2021 00:00:00'
                let date = components.date! as NSDate
                newPredicate = NSPredicate(format: "%K < %@", keyPath,date)
            case .lessThanOrEqualTo:
                // aDate < '4.5.2021 00:00:00'
                components.day = components.day! + 1
                let date = components.date! as NSDate
                newPredicate = NSPredicate(format: "%K < %@", keyPath,date)
            case .greaterThan:
                // aDate >= '4.5.2021 00:00:00'
                components.day = components.day! + 1
                let date = components.date! as NSDate
                newPredicate = NSPredicate(format: "%K >= %@", keyPath,date)
            case .greaterThanOrEqualTo:
                // aDate >= '3.5.2021 00:00:00'
                let date = components.date! as NSDate
                newPredicate = NSPredicate(format: "%K >= %@", keyPath,date)
            case .equalTo:
                // aDate >= '3.5.2021 00:00:00' AND aDate < '4.5.2021 00:00:00'
                let startDate = components.date! as NSDate
                components.day = components.day! + 1
                let endDate = components.date! as NSDate
                newPredicate = NSPredicate(format: "%K >= %@ AND %K < %@", keyPath, startDate, keyPath, endDate)
            case .notEqualTo:
                // NOT (aDate >= '3.5.2021 00:00:00' AND aDate < '4.5.2021 00:00:00')
                let startDate = components.date! as NSDate
                components.day = components.day! + 1
                let endDate = components.date! as NSDate
                newPredicate = NSPredicate(format: "NOT (%K >= %@ AND %K < %@)", keyPath, startDate, keyPath, endDate)
            default:
                newPredicate = predicate
        }
    }
    return newPredicate
}
于 2021-05-10T16:34:29.240 回答
0

感谢 Willeke 的回答,我能够解决它。我想让你参与整个解决方案。

  1. 创建自定义类CustomRowTemplate:NSPredicateEditorRowTemplate
  2. 覆盖 func 谓词,请参见上面 Willeke 的代码。这可以访问您希望过滤的日期,并创建具有当天日期/时间范围的谓词。
    override func predicate(withSubpredicates subpredicates: [NSPredicate]?) -> NSPredicate
  1. 在属性检查器中,对于 predicateEditor ,为 keypath 和 date 创建一个新的 Rowtemplate。然后将其类更改为 CustomRowTemplate

  2. 就这样。

于 2021-05-18T09:16:45.137 回答