这是我第一次尝试同时使用ARC和Core Data。我似乎无法弄清楚为什么我的代码崩溃了。

在.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" inManagedObjectContext:[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.


基本上,每当我尝试使用字符串以外的其他类型时,都会在该特定行上发生EXEC崩溃。当我将字符串用于所有内容时,这很好。在my.xcdatamodeld文件中,将myFloat设置为FLOAT,将myBool设置为BOOLEAN

kill
error while killing target (killing anyway): warning: error on line 2184 of "/SourceCache/gdb/gdb-1708/src/gdb/macosx/macosx-nat-inferior.c" in function "void macosx_kill_inferior_safe()": (os/kern) failure (0x5x)
quit
Program ended with exit code: 0

最佳答案

您不能将@dynamic用于原语(例如float和BOOL),因为Core Data不会为其创建实现。

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

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

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

反之亦然,设置myFloat和myBool时,您需要将它们存储在NSNumber中,例如BOOL b = [[user isMyBool] boolValue];[user setMyFloat:[NSNumber numberWithFloat:f]];

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

@property (nonatomic, strong) NSNumber *myBool;
@property (nonatomic, strong) NSNubmer *myFloat;


但是您可以同时保留它们的[user setMyBool:[NSNumber numberWithBool:b]];

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

要实现getter和setter,您需要对KVC / KVO和Core Data有所了解。简而言之:由于Core Data不会为您提供服务,因此您需要告诉系统何时要访问或更改属性,以及何时要完成访问或更改属性。在“将要访问/更改”和“已进行访问/更改”之间,您可以自由检索或修改属性。另一个警告是,Core Data仍然无法保存BOOL并直接浮动,因此在获取和设置时,它们必须打包到NSNumbers中或从NSNumbers中解包。

此外,您不能调用@dynamic[self setValue:ForKey:];,因为这会导致您所在的方法自行调用并陷入无限循环。 Core Data通过允许您获取和设置值而不用调用[self valueForKey:@""];[self setPrimitiveValue:ForKey:]来实现自己的实现来解决此用例。注意:primiteValueForKey与基本类型(int,float,BOOL)无关,而只是用于直接获取和设置Core Data中的值的方法的名称。

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"];
}

关于iphone - iPhone Core Data因ARC而崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8303470/

10-14 22:04
查看更多