iPhone核心数据因ARC崩溃

iPhone核心数据因ARC崩溃,iphone,core-data,ios4,ios5,Iphone,Core Data,Ios4,Ios5,这是我第一次尝试同时使用ARC和Core数据。我似乎不明白为什么我的代码会崩溃 在.h中,我有: @interface Foo : NSObject { } @property (nonatomic,strong) NSString *name; @property (nonatomic,strong) NSString *email; @property (nonatomic) BOOL myBool; @property (nonatomic) float myFloat; 在下午 @im

这是我第一次尝试同时使用ARC和Core数据。我似乎不明白为什么我的代码会崩溃

在.h中,我有:

@interface Foo : NSObject {
}
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSString *email;
@property (nonatomic) BOOL myBool;
@property (nonatomic) float myFloat;
在下午

@implementation User

@dynamic name;
@dynamic email;
@dynamic myBool;
@dynamic myFloat;
User*User=(User*)[NSEntityDescription insertNewObjectForEntityForName:@“User”在managedObjectContext:[appDelegate managedObjectContext]]中

[user setName:[[[dictionary objectForKey:@"user"] objectForKey:@"user"]objectForKey:@"name"]];
[user setEmail:[[[dictionary objectForKey:@"user"] objectForKey:@"user"]objectForKey:@"email"]];
[user setAuthorisation_token:[[[dictionary objectForKey:@"user"] objectForKey:@"user"]objectForKey:@"authentication_token"]];
[user setMyFloat:5]; <------ crash when set to anything other than 0 (eg,setting to FALSE will crash it).
[user setMyBool:FALSE]; <---- crash when set this to anything other than 0.

不能将@dynamic用于原语(如float和BOOL),因为核心数据不会为它们创建实现

因此,代码崩溃的原因是,当您使用
@dynamic
时,您告诉编译器“我保证这些getter和setter的实现将在运行时可用”。但由于核心数据不创建它们,所以代码尝试调用不存在的方法

相反,您可以做两件事:对BOOL和float使用NSNumber,或者实现您自己的getter和setter

使用NSNumber:
核心数据仅使用对象而不使用基本体,但可以在模型中指定布尔值或浮点值。当您调用
[user myFloat]
时,实际上会返回一个NSNumber,其中包含浮点值。要访问原语,请调用
float f=[[user myFloat]floatValue]。布尔值也是一样,它也存储在一个NSNumber中。因此,当您尝试访问它时,您将返回一个需要调用的NSNumber
BOOL b=[[user isMyBool]boolValue]
以获取原语

同样的事情反过来说,当设置myFloat和myBool时,您需要将它们存储在NSNumber中,例如,
[用户设置myFloat:[NSNumber numberWithFloat:f]]
[用户设置MyBool:[NSNumber numberWithBool:b]]

要使用这种方法,您必须将最后两个属性更改为

@property (nonatomic, strong) NSNumber *myBool;
@property (nonatomic, strong) NSNubmer *myFloat;
但是您可以为这两个对象保留
@动态

实现您自己的getter和setter:
为了方便起见,您可能希望“用户”对象直接获取和设置基本类型float和BOOL。在这种情况下,应该将属性保留为float和bool,并在实现文件(.m)中删除myFloat和myBool的
@dynamic

要实现getter和setter,您需要了解一些KVC/KVO和核心数据。简言之:您需要告诉系统何时您将要访问或更改一个属性,何时您完成了访问或更改,因为核心数据不会帮您完成。在“将访问/更改”和“已访问/更改”之间,您可以自由检索或修改属性。还有一个警告是,核心数据仍然无法直接保存BOOL和float,因此在获取和设置时需要将它们打包到NSNumber中并从NSNumber中解包

此外,您不能调用
[self-setValue:ForKey:]
[自我价值观][self-setPrimitiveValue:ForKey:
[self-primitivevalueforkey:
允许您获取和设置值,而不影响您自己的实现来解决此用例注意:primiteValueForKey与基元类型(int、float、BOOL)无关,只是用于直接获取和设置核心数据中的值的方法的名称

float和BOOL的实现如下所示:

- (float)myFloat 
{
    [self willAccessValueForKey:@"myFloat"];
    float f = [[self primitiveValueForKey:@"myFloat"] floatValue];
    [self didAccessValueForKey:@"myFloat"];
    return f;
}

- (void)setMyFloat:(float)f 
{
    [self willChangeValueForKey:@"myFloat"];
    [[self setPrimitiveValue:[NSNumber numberWithFloat:f] forKey:@"myFloat"];
    [self didChangeValueForKey:@"myFloat"];
}

- (BOOL)isMyBool 
{
    [self willAccessValueForKey:@"myBool"];
    BOOL b = [[self primitiveValueForKey:@"myBool"] boolValue];
    [self didAccessValueForKey:@"myBool"];
    return b;
}

- (void)setMyBool:(BOOL)b 
{
    [self willChangeValueForKey:@"myBool"];
    [[self setPrimitiveValue:[NSNumber numberWithBool:b] forKey:@"myBool"];
    [self didChangeValueForKey:@"myBool"];
}

那些.h和.m文件似乎不是来自同一个对象。当然应该是@interface User:NSManagedObject?太好了,我更新了答案,提供了更多信息和一个有一些好处的替代解决方案。非常感谢!我已经用头撞了这个好几个小时了。
- (float)myFloat 
{
    [self willAccessValueForKey:@"myFloat"];
    float f = [[self primitiveValueForKey:@"myFloat"] floatValue];
    [self didAccessValueForKey:@"myFloat"];
    return f;
}

- (void)setMyFloat:(float)f 
{
    [self willChangeValueForKey:@"myFloat"];
    [[self setPrimitiveValue:[NSNumber numberWithFloat:f] forKey:@"myFloat"];
    [self didChangeValueForKey:@"myFloat"];
}

- (BOOL)isMyBool 
{
    [self willAccessValueForKey:@"myBool"];
    BOOL b = [[self primitiveValueForKey:@"myBool"] boolValue];
    [self didAccessValueForKey:@"myBool"];
    return b;
}

- (void)setMyBool:(BOOL)b 
{
    [self willChangeValueForKey:@"myBool"];
    [[self setPrimitiveValue:[NSNumber numberWithBool:b] forKey:@"myBool"];
    [self didChangeValueForKey:@"myBool"];
}