在核心数据中存储可选的NSNumber

时间:2021-04-27 16:59:46

In my core data model, I have an entity with an optional NSNumber attribute.

在我的核心数据模型中,我有一个具有可选NSNumber属性的实体。

How do I test to see if the value in that attribute is valid or not?

如何测试该属性中的值是否有效?

When I test for nil... doesn't work.

当我测试为零时......不起作用。

[self numberAttribute] == nil // always returns NO

When I test for a zero value int, that doesn't work.

当我测试零值int时,这不起作用。

[[self numberAttribute] intValue] == 0  // always returns no

As a matter of fact, [[self numberAttribute] intValue]] returns something that looks suspiciously like a pointer to a memory address.

事实上,[[self numberAttribute] intValue]]返回一些看起来像是指向内存地址的指针。

Anyone have any idea what I am doing wrong?

任何人都知道我做错了什么?

EDIT: OK, the bug was in a totally unrelated part of the code. NSNumber and Core Data are functioning exactly as one would expect. That said, I am going to go with the suggested approach of making the attribute non-optional and specifying 0 as the default value.

编辑:好的,错误是代码中完全不相关的部分。 NSNumber和Core Data的功能完全符合预期。也就是说,我将采用建议的方法,使属性非可选,并指定0作为默认值。

Just putting this note here for a little while for anyone who was watching this question, then I am deleting it.

对于正在观看这个问题的人来说,只需将此注释放在这里一段时间,然后我将其删除。

3 个解决方案

#1


According to the documentation,

根据文件,

You can specify that an attribute is optional—that is, it is not required to have a value. In general, however, you are discouraged from doing so—especially for numeric values (typically you can get better results using a mandatory attribute with a default value—in the model—of 0). The reason for this is that SQL has special comparison behavior for NULL that is unlike Objective-C's nil. NULL in a database is not the same as 0, and searches for 0 will not match columns with NULL.

您可以指定属性是可选的 - 也就是说,不需要具有值。但是,一般情况下,不鼓励您这样做 - 特别是对于数值(通常,您可以使用具有默认值的强制属性 - 在0的模型中获得更好的结果)。原因是SQL对NULL有特殊的比较行为,与Objective-C的nil不同。数据库中的NULL与0不同,搜索0将不匹配NULL的列。

false == (NULL == 0)
false == (NULL != 0)

Moreover, NULL in a database is not equivalent to an empty string or empty data blob, either:

此外,数据库中的NULL不等于空字符串或空数据blob:

false == (NULL == @"")
false == (NULL != @"")

So, try a test with NULL, which is not nil. Better yet, set a default and change the attribute to be non-optional. That's what I've ended up doing in my models, and in practice it works quite well.

因此,尝试使用NULL进行测试,这不是零。更好的是,设置默认值并将属性更改为非可选属性。这就是我最终在我的模型中所做的事情,并且在实践中它的效果非常好。

Edit: See my comment above. I tried creating a new managed object with an optional attribute not set, and it was nil.

编辑:请参阅上面的评论。我尝试创建一个未设置可选属性的新托管对象,它是零。

BOOL isNil = ([newManagedObject numberAttribute] == nil);  //equals YES

Another edit: I came back to this later and checked out an object loaded from the cache in the debugger (gdb is your friend!). It was trying to access memory location 0x0, which is NULL.

另一个编辑:我后来回到这里并检查了从调试器中的缓存加载的对象(gdb是你的朋友!)。它试图访问内存位置0x0,这是NULL。

#2


If you are getting a large value back that looks like a pointer, perhaps it is NaN (not a number)?

如果你得到一个看起来像指针的大值,也许它是NaN(不是数字)?

If so, you could check with:

如果是这样,您可以查看:

 isnan([[self numberAttribute] doubleValue])

Or, possibly it is some other constant along the lines of NSNotFound (though probably more Core Data specific).

或者,它可能是NSNotFound的其他常量(虽然可能更具核心数据)。

#3


If it looks like a pointer, it may be a pointer to NSNumber instance. Make sure you don't have mismatch between core data model and the class (e.g. NSInteger where NSNumber* is expected).

如果它看起来像一个指针,它可能是一个指向NSNumber实例的指针。确保核心数据模型与类之间没有不匹配(例如,NSInteger需要NSNumber *)。

If you have scalar in your class, then you need to note that yourself in setNilValueForKey:.

如果你的班级有标量,那么你需要在setNilValueForKey中注意自己:

#1


According to the documentation,

根据文件,

You can specify that an attribute is optional—that is, it is not required to have a value. In general, however, you are discouraged from doing so—especially for numeric values (typically you can get better results using a mandatory attribute with a default value—in the model—of 0). The reason for this is that SQL has special comparison behavior for NULL that is unlike Objective-C's nil. NULL in a database is not the same as 0, and searches for 0 will not match columns with NULL.

您可以指定属性是可选的 - 也就是说,不需要具有值。但是,一般情况下,不鼓励您这样做 - 特别是对于数值(通常,您可以使用具有默认值的强制属性 - 在0的模型中获得更好的结果)。原因是SQL对NULL有特殊的比较行为,与Objective-C的nil不同。数据库中的NULL与0不同,搜索0将不匹配NULL的列。

false == (NULL == 0)
false == (NULL != 0)

Moreover, NULL in a database is not equivalent to an empty string or empty data blob, either:

此外,数据库中的NULL不等于空字符串或空数据blob:

false == (NULL == @"")
false == (NULL != @"")

So, try a test with NULL, which is not nil. Better yet, set a default and change the attribute to be non-optional. That's what I've ended up doing in my models, and in practice it works quite well.

因此,尝试使用NULL进行测试,这不是零。更好的是,设置默认值并将属性更改为非可选属性。这就是我最终在我的模型中所做的事情,并且在实践中它的效果非常好。

Edit: See my comment above. I tried creating a new managed object with an optional attribute not set, and it was nil.

编辑:请参阅上面的评论。我尝试创建一个未设置可选属性的新托管对象,它是零。

BOOL isNil = ([newManagedObject numberAttribute] == nil);  //equals YES

Another edit: I came back to this later and checked out an object loaded from the cache in the debugger (gdb is your friend!). It was trying to access memory location 0x0, which is NULL.

另一个编辑:我后来回到这里并检查了从调试器中的缓存加载的对象(gdb是你的朋友!)。它试图访问内存位置0x0,这是NULL。

#2


If you are getting a large value back that looks like a pointer, perhaps it is NaN (not a number)?

如果你得到一个看起来像指针的大值,也许它是NaN(不是数字)?

If so, you could check with:

如果是这样,您可以查看:

 isnan([[self numberAttribute] doubleValue])

Or, possibly it is some other constant along the lines of NSNotFound (though probably more Core Data specific).

或者,它可能是NSNotFound的其他常量(虽然可能更具核心数据)。

#3


If it looks like a pointer, it may be a pointer to NSNumber instance. Make sure you don't have mismatch between core data model and the class (e.g. NSInteger where NSNumber* is expected).

如果它看起来像一个指针,它可能是一个指向NSNumber实例的指针。确保核心数据模型与类之间没有不匹配(例如,NSInteger需要NSNumber *)。

If you have scalar in your class, then you need to note that yourself in setNilValueForKey:.

如果你的班级有标量,那么你需要在setNilValueForKey中注意自己: