Pregunta

Esta es la primera vez que intento usar datos de ARC y Core. Parece que no puedo averiguar por qué mi código se está bloqueando.

En el .h tengo:

@interface Foo : NSObject {
}
@property (nonatomic,strong) NSString *name;
@property (nonatomic,strong) NSString *email;
@property (nonatomic) BOOL myBool;
@property (nonatomic) float myFloat;

en ellos

@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.

Básicamente, cada vez que intento usar un tipo que no sea una cadena, estoy recibiendo un bloqueo ejecutivo en esa línea en particular. Cuando uso cadenas para todo, está bien. En el archivo my.xcdatamodeld tengo myfloat configurado para flotar y mybool establecido en 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
¿Fue útil?

Solución

No puede usar @dynamic para primitivas (como Float y Bool) porque Core Data no creará implementaciones para ellos.

Entonces, la razón por la que su código se bloquea es porque cuando usa @dynamic Le está diciendo al compilador "Prometo que una implementación para estos getters y setters estará disponible en tiempo de ejecución". Pero dado que Core Data no los crea, su código intenta llamar a métodos que no existen.

En su lugar, hay dos cosas que puede hacer: use un nsnumber tanto para el bool como para el flotador o implementen sus propios getters y setters.

Usando nsnumber:
Core Data solo usa objetos y no primitivas, pero puede especificar boolean o flotación en el modelo. Cuando usted llama [user myFloat] De hecho, obtendrá un nsnumber con el valor flotante dentro de él. Para acceder a la primitiva que llamas float f = [[user myFloat] floatValue];. Lo mismo ocurre con el booleano, también se almacena en un número nsnumber. Entonces, cuando intente acceder a él, recuperará un Nsnumber al que necesita llamar BOOL b = [[user isMyBool] boolValue]; Para recuperar el primitivo.

Lo mismo va al revés, al configurar myfloat y mybool, debes almacenarlos dentro de un número nsnumber, por ejemplo [user setMyFloat:[NSNumber numberWithFloat:f]]; y [user setMyBool:[NSNumber numberWithBool:b]];.

Para usar este enfoque Tendrías que cambiar tus dos últimas propiedades a

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

Pero puedes mantener el @dynamic para ambos.

Implementando sus propios getters y setters:
Para su conveniencia, es posible que desee que su objeto "Usuario" obtenga y establezca directamente los tipos primitivos, flotando y bool. En ese caso, debe mantener las propiedades como flotación y bool y en su archivo de implementación (.m) eliminar el @dynamic Líneas para myfloat y mybool.

Para implementar el Getter y Setter, necesita saber un poco sobre los datos KVC/KVO y Core. En resumen: debe decirle al sistema cuándo está a punto de acceder o cambiar una propiedad y cuando haya terminado de acceder o cambiarlo, ya que los datos principales no lo harán por usted. Entre el "Acceso/Cambio" y "Acceso/Cambio", puede recuperar o modificar las propiedades. Una advertencia más es que los datos del núcleo aún no pueden guardar el bool y flotar directamente, por lo que deben empaquetarse y desempaquetarse de NSNumbers al obtener y configurar.

Además, no puedes llamar [self setValue:ForKey:]; o [self valueForKey:@""]; Porque eso causaría el método en el que se encuentra a sí mismo y lo arroje a un bucle infinito. Core Data resuelve este caso de uso al permitirle obtener y establecer el valor sin alcanzar su propia implementación llamando [self setPrimitiveValue:ForKey:] y [self primiveValueForKey:]. Nota: Primitevalueforkey no tiene nada que ver con los tipos primitivos (int, float, bool), pero es solo el nombre de los métodos que utiliza para obtener y establecer valores en los datos principales directamente.

La implementación para su flotación y bool se vería algo así:

- (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"];
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top