iPhone核心数据因ARC崩溃
这是我第一次尝试同时使用ARC和Core数据。我似乎不明白为什么我的代码会崩溃 在.h中,我有: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
@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中。因此,当您尝试访问它时,您将返回一个需要调用的NSNumberBOOL 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"];
}