Вопрос

Я впервые пытаюсь использовать как дуговые, так и основные данные. Кажется, я не могу понять, почему мой код сбивается.

В .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 на этой конкретной строке. Когда я использую строки для всего, все в порядке. В моем файле.xcdatamodeld у меня есть Myfloat, чтобы Float, и Mybool установлен на логический

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), потому что основные данные не будут создавать для них реализации.

Итак, причина, по которой ваш код сбивается, заключается в том, что когда вы используете @dynamic Вы говорите компилятору: «Я обещаю, что реализация для этих Getters и Setters будет доступна во время выполнения». Но поскольку основные данные не создают их, ваш код пытается вызовать методы, которые не существуют.

Вместо этого есть две вещи, которые вы могли бы сделать: используйте NSNumber как для Bool, так и для плавания или реализовать свои собственные добычи и сеттеры.

Используя nsnumber:
Данные Core используют только объекты, а не примитивы, но вы можете указать Boolean или Float в модели. Когда вы звоните [user myFloat] Вы действительно получите NSNumber обратно с поплавкой внутри него. Чтобы получить доступ к примитиву, вы затем звоните float f = [[user myFloat] floatValue];. Анкет То же самое касается логического, оно также хранится в NSNumber. Поэтому, когда вы попытаетесь получить доступ к нему, вы вернете NSNumber, что вам нужно позвонить BOOL b = [[user isMyBool] boolValue]; Чтобы вернуть примитиву.

То же самое происходит наоборот, при установлении Myfloat и Mybool вам нужно хранить их в NSNumber, например, [user setMyFloat:[NSNumber numberWithFloat:f]]; а также [user setMyBool:[NSNumber numberWithBool:b]];.

Чтобы использовать этот подход вам придется изменить свои последние два свойства на

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

Но вы можете сохранить @dynamic Для них обоих.

Реализация ваших собственных Getters и Setters:
Для вашего удобства вы можете захотеть получить ваш «пользовательский» объект, и устанавливал примитивные типы, плавание и Bool напрямую. В этом случае вы должны сохранить свойства как float и bool и в вашем файле реализации (.m) удалить @dynamic Линии для Myfloat и Mybool.

Чтобы реализовать Getter и Setter, вам нужно немного узнать о данных KVC/KVO и Core. Короче говоря: вам нужно сообщить системе, когда вы собираетесь получить доступ или изменить свойство, и когда вы закончите доступ или измените ее, поскольку основные данные не сделают это для вас. Между «доступом/изменением» и «ДЕЛАЙТЕ ДЕЛА/ПРИМЕНЕНИЕ», вы можете получить или изменить свойства. Еще одно предостережение заключается в том, что основные данные все еще не могут сохранить Bool и плавать напрямую, поэтому их необходимо упаковать и невопаковывать от NSNumbers при получении и настройке.

Далее вы не можете позвонить [self setValue:ForKey:]; или же [self valueForKey:@""]; Потому что это приведет к тому, что метод, который вы приходите, позвонить себе и бросить вас в бесконечный цикл. Данные ядра решают этот вариант использования, позволяя вам получить и установить значение, не достигая собственной реализации, вызывая [self setPrimitiveValue:ForKey:] а также [self primiveValueForKey:]. Примечание: PrimiteValueForkey не имеет ничего общего с примитивными типами (int, float, bool), но это просто название методов, которые вы используете для получения и установки значений в основных данных напрямую.

Реализация для вашего поплавка и 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"];
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top