Вы не можете использовать @dynamic для примитивов (таких как float и BOOL), потому что Core Data не создаст для них реализации.
Поэтому причина, по которой ваш код падает, заключается в том, что при использовании @dynamic
Вы говорите компилятору: «Я обещаю, что реализация для этих методов получения и установки будет доступна во время выполнения».Но поскольку Core Data их не создает, ваш код пытается вызвать методы, которых не существует.
Вместо этого вы можете сделать две вещи: использовать NSNumber для BOOL и float или реализовать свой.собственные методы получения и установки.
Использование NSNumber: Базовые данные используют только объекты, а не примитивы, но вы можете указать логическое значение или значение с плавающей точкой в модели.Когда вы вызываете [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
для них обоих.
Реализация собственных методов получения и установки: Для вашего удобства вам может потребоваться, чтобы ваш пользовательский объект получал и устанавливал типы примитивов float и BOOL напрямую.В этом случае вы должны сохранить свойства как float и bool и в вашем файле реализации (.m) удалите строки @dynamic
для myFloat и myBool.
Для реализации метода получения и установки вам нужно немного знатьо KVC / KVO и основных данных.Вкратце: вам нужно сообщить системе, когда вы собираетесь получить доступ к свойству или изменить его, а также когда вы закончите доступ к нему или его изменение, поскольку Core Data не сделает этого за вас.Между «будет доступ / изменение» и «сделал доступ / изменение» вы можете свободно извлекать или изменять свойства.Еще одно предостережение в том, что Core Data по-прежнему не может сохранять BOOL и напрямую перемещаться, поэтому их нужно упаковывать и распаковывать из NSNumbers при получении и настройке.
Кроме того, вы не можете вызвать [self setValue:ForKey:];
или [self valueForKey:@""];
, потому что это приведет к тому, что метод, в котором вы находитесь, вызовет сам себя и бросит вас в бесконечный цикл.Core Data решает этот вариант использования, позволяя вам получить и установить значение, не затрагивая вашу собственную реализацию, вызывая [self setPrimitiveValue:ForKey:]
и [self primiveValueForKey:]
. Примечание: 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"];
}