EXC_BAD_ACCESS 设置核心数据实体属性
Posted
技术标签:
【中文标题】EXC_BAD_ACCESS 设置核心数据实体属性【英文标题】:EXC_BAD_ACCESS on setting Core Data entity property 【发布时间】:2014-03-24 21:48:29 【问题描述】:我发现人们在 Core Data 模型中使用整数类型存在一些问题,但随后尝试在代码中使用整数而不将复选框设置为使用标量。但是,我实际上正在这样做。
-
在实体上创建一个整数 64 属性
从该实体创建一个 NSManagedObject 子类
选中“对原始数据类型使用标量属性”框。
这会生成:
@interface State : NSManagedObject
@property (nonatomic) int64_t serverId;
@end
但是,然后,在运行时,我会使用以下代码得到 EXC_BAD_ACCESS 错误:
int64_t someValue = 313;
State *state = ... // standard [NSEntityDescription insert code
state.serverId = someValue;
其中 'state' 是 NSManagedObject 子类,serverId 是 Integer 64 属性。 但是,以下代码有效:
state.serverId = [NSNumber numberFromInt:someValue];
但是,由于 serverId 实际上被声明为 int64_t,这会导致警告。而且,实际上尝试访问该值会给出可能是指针地址的东西(尽管 %@ 看起来像我所期望的那样)。
所以,我想我的问题是,Core Data 中的什么东西卡在了我的 int64_t 是 NSNumber 上?查看模型和 NSAttributeDescription,它是一个 NSInteger64AttributeType。
我认为可能与此有关的事情:
忘记选中该框并重新生成类 更新架构并迁移首先,这似乎是一种常见情况,我已经尝试过,但正如预期的那样,我无法重现我的问题。对于第二种情况,我删除了我的模型文件并重新创建了所有内容,删除了我的 DerivedData 目录。
【问题讨论】:
【参考方案1】:如果您计划同时支持 32 位和 64 位架构,您将希望远离标量。
首先阅读CocoaTouch 64 Bit Guide
在你的代码中注意int
和NSInteger
在model
中使用Integer32
或Integer64
。位大小取决于应用程序对数字空间的要求。如果您的 serverID 都在 313 左右,您应该可以使用 32 位,如果您的数字非常大,请使用 integer64。
我了解您目前使用的是 integer64。为了避免迁移的需要,现在只使用 integer64。但也要针对 32 位架构测试您的应用。
在实体类中使用NSNumber,不要对存储在存储中的属性使用标量。
@interface State : NSManagedObject
@property (nonatomic, retain) NSNumber *serverId;
@end
@implementation State
@dynamic serverId; // this will create the default accessor for you
@end
CoreData 会神奇地将 Integer32 或 Integer64 转换为 NSNumber,您无需担心转换警告。
在您的应用代码中使用numberFromInteger
而不是numberFromInt
state.serverId = [NSNumber numberFromInteger:someValue];
自定义访问器为整数
如果你有很多 NSIntegers 并且你想写类似的东西
NSInteger someInteger;
state.serverIdInteger = someInteger;
// or
someInteger = state.serverIdInteger;
那么您将需要serverID
的自定义访问器。你的模型没有改变,改变的是实体类。
@interface State : NSManagedObject
@property (nonatomic, retain) NSNumber *serverId;
@property (nonatomic) NSInteger serverIdInteger; //custom accessor
@end
@implementation State
@dynamic serverId; // this will create the default *serverId* accessor
// now do custom accessor
-(void)setServerIdInteger:(NSInteger)anInteger
[self willChangeValueForKey:@"serverId"];
[self setServerId:[NSNumber numberWithInteger:anInteger]];
[self didChangeValueForKey:@"serverId"];
-(NSInteger)serverIdInteger
[self willAccessValueForKey:@"serverId"];
NSNumber *tmpValue = [self serverId];
[self didAccessValueForKey:@"serverId"];
return (tmpValue!=nil) ? [tmpValue integerValue] : 0;
@end
【讨论】:
一个 int64_t 在任何平台上都是 64 位的。这就是 64 位 int 的定义。以上是关于EXC_BAD_ACCESS 设置核心数据实体属性的主要内容,如果未能解决你的问题,请参考以下文章