【问题标题】:NSPredicate working for more than, but not less thanNSPredicate 工作大于但不小于
【发布时间】:2012-10-05 05:39:04
【问题描述】:

我在使用谓词从 Core Data 存储中获取结果时遇到问题。我的应用程序所做的是根据一个或多个谓词从存储中获取结果,并向您显示基于所有谓词的结果或基于每个谓词的结果。

它在大多数情况下都可以正常工作,除了我无法让“小于”查询工作。这是我正在使用的代码:

case CriteriaSelectionIsLessThan:
        pred = [NSPredicate predicateWithFormat:@"ANY value.attribute.name == %@ AND ANY value.%@ < %@", [attribute name], keyPath, [[activeValue value] value]];
        break;
case CriteriaSelectionIsMoreThan:
        pred = [NSPredicate predicateWithFormat:@"ANY value.attribute.name == %@ AND ANY value.%@ > %@", [attribute name], keyPath, [[activeValue value] value]];
        break;

“超过”谓词的代码工作正常,它返回查询的数据集,例如 > 1970(一年)。当我尝试使用“小于”谓词(例如

[[activeValue value] value] 是一个 NSNumber。

我这辈子都想不通 - 谓词完全相同,但有一个字符不同!

我们将不胜感激。如果您需要更多代码/信息,请告诉我。

编辑:这是我在从 JSON 导入时映射数据类型的方式:

[attrib setDataType:[NSNumber numberWithInteger:[[attribute valueForKey:@"type"] integerValue]]];...

// Set the correct data type of the value
switch ([[attrib dataType] integerValue]) {
    case AttributeDataTypeNumber:
        [value setNumberValue:[NSNumber numberWithInteger:[valueForKey integerValue]]];
        break;
    case AttributeDataTypeString:   
        [value setStringValue:(NSString *)valueForKey];
        break;
    case AttributeDataTypeDate: {
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"dd-MM-YYYY"];
        [value setDateValue:[df dateFromString:(NSString *)valueForKey]];
    }
        break;
    case AttributeDataTypeBool:
        [value setBooleanValue:[NSNumber numberWithBool:[valueForKey boolValue]]];
        break;
}

看,我的 JSON 中的数据类型保证是正确的,因为我在导入它之前检查它(而不是在应用程序中)。即使我构建了一个明确表示我想要某个数据类型的谓词(例如 value.attribute.dataType == 1 ,其中 1 是枚举中的数字),它仍然不起作用。真的很奇怪。

【问题讨论】:

  • 不确定这是否会有所帮助,但是否有可能将整个 keypath,而不仅仅是 value 后面的内容,放入单个表达式(将评估为 value.RESTOFKEYPATH),然后使用 @ 987654323@ 作为格式说明符,检查起来会很有趣,但不太可能。无论如何,这是第一件让我感到震惊的事情。甚至像[NSPredicate predicateWithFormat:@"ANY value.attribute.name == %@ AND ANY %K &gt; %@", [attribute name], [NSString stringWithFormat:@"value.%@",keyPath], [[activeValue value] value]]
  • 不幸的是也不起作用!我尝试创建一个没有任何动态变量的谓词(即显式键入表达式),但它仍然不起作用。适用于超过,但不低于。我已经检查过数据是否可以正常导入到 Core Data 中 - 可以。我只是无法确定这里的问题是什么:(
  • 很奇怪!当您在调试器中打印谓词的描述时,您会看到什么?此外,当使用您知道它应该为假的对象的特定实例进行评估时,它是否评估为 YES - 即它是否发生在获取请求上下文之外?并且您对值名称部分也进行了硬编码,结果相同?我的另一个奇怪的想法是将它们分成两个谓词,一个用于命名一个用于比较,然后重建一个复合“和”谓词。没有合乎逻辑的理由应该起作用,所以请随意忽略该建议:)

标签: objective-c ios nspredicate predicate


【解决方案1】:

您确定它返回的是整个数据集吗?我猜你为 lessThan 操作得到的值是 value.%@ 的 NULL 值的对象

编辑:

以下是我如何动态处理模型的属性:

for (NSEntityDescription *entity in [self.managedObjectModel entities]) // self.managedObjectModel is a NSManagedObjectModel
{
    for (NSAttributeDescription *attribute in [[entity attributesByName] allValues])
    {
        NSString *key = [attribute name];
        // do something with key
        switch ([attribute attributeType])
        {
            case NSBooleanAttributeType:
            case NSInteger16AttributeType:
            case NSInteger32AttributeType:
            case NSInteger64AttributeType:
            case NSDecimalAttributeType:
            case NSDoubleAttributeType:
            case NSFloatAttributeType:
                // do something with numeric types
                break;
            case NSStringAttributeType:
                // do something with string types
                break;
            case NSDateAttributeType:
                // do something with date types
                break;
         }
    }
}

每个case 处理谓词的方式不同。您可以缓存 key:type 关系以提高性能。

【讨论】:

  • 你可以在这里找到一些东西。我必须这样做的原因是每个值都可以是不同的数据类型(字符串、日期、数字)。起初,我尝试使用 Transient 属性,但是在将 NSPredicates 放在一起时,我遇到了 NSNumbers 的问题(它没有正确地转换它们并且返回了不正确的结果) - 这与 SQLite 将所有内容存储为二进制文件有关。因此,每个值都有一个 'stringValue'、'numberValue'... 等属性。当它们不是该类型时,其他值为零。我可能需要检查对象的数据类型。
  • 是的,这个问题看起来很熟悉。我还写了一个像这样的动态搜索构建器,而 nil results 使事情变得一团糟。这是因为如果对象没有密钥,[NSObject valueForKey:] 返回 nil。您可以在谓词中包含AND value.%@ != nil,但这也会排除某些keyPaths 具有有效nil 值的对象。或者您可以将所有已知的 keyPaths 映射到它们的类型,然后相应地构建我们的 NSPredicates
  • 我认为这是罪魁祸首。目前,我已经通过将非数字值的 numberValue 属性显式设置为 9 万亿或其他值来修复它(稍后我将不得不回到它)。你的答案是正确的,所以我会标记它。你最终是如何解决你的问题的?您是否必须重新进行数据库设计?
  • 我为此添加了一个 sn-p。永远不需要重新设计数据库。
  • 顺便说一句,你可能误会了。构建谓词时不会调用那里的循环代码。它用于将实体属性名称映射到它们的类型。然后,当需要构建谓词时,创建一个适合属性类型的谓词。
【解决方案2】:

我想通了!如果其他人遇到了这个问题,我是这样解决的:

[NSPredicate predicateWithFormat:@"SUBQUERY(value, $val, $val.attribute.name == %@ && $val.%@ < %@).@count > 0", [attribute name], keyPath, [[activeValue value] value]]

我认为这是因为它是一对多键,必须根据多个条件进行匹配。当我使用 ANY 关键字时,我认为这是返回我不想要的值的罪魁祸首。现在就像一个魅力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多