Question

Ceci est ma première fois en essayant d'utiliser les deux ARC et Core Data. Je ne peux pas sembler comprendre pourquoi mon code se bloque.

dans le .h je:

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

dans le .m

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

En fait chaque fois que j'essaie d'utiliser un type autre qu'une chaîne que je reçois crash EXEC sur cette ligne particulière. Quand je l'utilise pour tout ce cordes est bien. Dans le fichier my.xcdatamodeld J'ai mis myFloat FLOTTER et ensemble 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
Était-ce utile?

La solution

Vous ne pouvez pas utiliser @dynamic pour les primitives (comme flotteur et BOOL) parce que les données de base ne va pas créer des implémentations pour eux.

Alors la raison pour laquelle votre code se bloque parce que lorsque vous utilisez @dynamic vous dites au compilateur « Je promets qu'une mise en œuvre de ces accesseurs sera disponible lors de l'exécution ». Mais puisque Core Data ne les crée pas alors votre code essaie de méthodes d'appel qui n'existe pas.

Au lieu de cela, il y a deux choses que vous pourriez faire:. Utilisez un NSNumber pour les deux BOOL et le flotteur ou mettre en œuvre vos propres accesseurs

Utilisation NSNumber: Les données de base utilise uniquement des objets et non des primitives mais vous pouvez spécifier booléenne ou flotter dans le modèle. Lorsque vous appelez [user myFloat] vous réellement obtenir un retour NSNumber avec la valeur du flotteur à l'intérieur. Pour accéder à la primitive puis appelez float f = [[user myFloat] floatValue]; vous. La même chose vaut pour le booléen, il obtient également stocké dans un NSNumber. Donc, lorsque vous essayez d'y accéder vous récupérerez un NSNumber que vous devez appeler BOOL b = [[user isMyBool] boolValue]; pour obtenir le dos primitif.

La même chose va l'inverse, lors de la mise myFloat et myBool, vous devez les stocker dans un NSNumber, par exemple [user setMyFloat:[NSNumber numberWithFloat:f]]; et [user setMyBool:[NSNumber numberWithBool:b]];.

Pour utiliser cette approche que vous auriez à changer vos deux derniers biens immobiliers à

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

mais vous pouvez garder le @dynamic pour les deux.

La mise en œuvre propres accesseurs: Pour votre commodité, vous voudrez peut-être votre objet « utilisateur » pour obtenir et définir les types primitifs, flotteur et BOOL, directement. Dans ce cas, vous devez conserver les propriétés comme flotteur et bool et dans votre fichier d'implémentation (.m) supprimer les lignes de @dynamic pour myFloat et myBool.

Pour mettre en œuvre le getter et setter vous devez savoir un peu KVC / KVO et Core Data. En bref: vous devez indiquer au système lorsque vous êtes sur le point d'accès ou de modifier une propriété et quand yo u fini d'accéder ou de le modifier, car les données de base ne le fera pas pour vous. Entre le « accédera / changement » et « accès / changement did » vous êtes libre de récupérer ou modifier les propriétés. Une mise en garde est plus que les données fondamentales ne peut toujours pas sauver BOOL et flotter directement, donc ils doivent être emballés dans et non emballés de NSNumbers lors de l'obtention et le réglage.

En outre, vous ne pouvez pas appeler [self setValue:ForKey:]; ou [self valueForKey:@""]; parce que causerait la méthode que vous pour lui-même appeler et vous jeter dans une boucle infinie. Core Data permet de résoudre ce cas d'utilisation en vous permettant d'obtenir et de définir la valeur sans toucher votre propre implémentation en appelant [self setPrimitiveValue:ForKey:] et [self primiveValueForKey:]. Remarque: primiteValueForKey n'a rien à voir avec les types primitifs (int, float, BOOL), mais est juste le nom des méthodes que vous utilisez pour obtenir et valeurs définies dans base de données directement.

La mise en œuvre de votre flotteur et BOOL ressemblerait à quelque chose comme ceci:

- (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"];
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top