【问题标题】:EXC_BAD_ACCESS on setting Core Data entity propertyEXC_BAD_ACCESS 设置核心数据实体属性
【发布时间】:2014-03-24 21:48:29
【问题描述】:

我发现人们在 Core Data 模型中使用整数类型存在一些问题,但随后尝试在代码中使用整数而不将复选框设置为使用标量。但是,我实际上正在这样做。

  1. 在实体上创建一个整数 64 属性
  2. 从该实体创建一个 NSManagedObject 子类
  3. 选中“对原始数据类型使用标量属性”框。

这会生成:

@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 目录。

【问题讨论】:

    标签: objective-c core-data


    【解决方案1】:

    如果您计划同时支持 32 位和 64 位架构,您将希望远离标量。

    首先阅读CocoaTouch 64 Bit Guide

    在你的代码中注意intNSInteger

    model 中使用Integer32Integer64。位大小取决于应用程序对数字空间的要求。如果您的 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 的定义。
    猜你喜欢
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多