Domanda

Questa è la mia prima volta cercando di utilizzare sia ARC e Core Data. Io non riesco a capire perché il mio codice si blocca.

nel .h ho:

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

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

In pratica ogni volta che provo ad usare un tipo diverso da una stringa sto ottenendo incidente EXEC su quella particolare linea. Quando uso le stringhe per tutto ciò che è bene. Nel file di my.xcdatamodeld devo set myFloat di galleggiare e set myBool a BOOLEANO

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
È stato utile?

Soluzione

Non è possibile utilizzare @dynamic per primitive (come float e BOOL) perché Core Data non creerà implementazioni per loro.

Quindi, il motivo per cui il codice si blocca è perché quando si utilizza @dynamic si sta dicendo al compilatore "Prometto che un'implementazione per questi getter e setter saranno disponibili in fase di esecuzione". Ma dal momento che Core Data non li crea quindi i vostri tentativi di codice ai metodi di chiamata che non esiste.

Invece ci sono due cose che si potrebbero fare:. Utilizzare un NSNumber sia per il BOOL e il galleggiante o implementare il proprio getter e setter

Utilizzo NSNumber:
Core Data utilizza solo oggetti e non primitivi ma è possibile specificare booleano o galleggiare nel Modello. Quando si chiama [user myFloat] sarà effettivamente ottenere un posteriore NSNumber con il valore float al suo interno. Per accedere al primitivo allora chiamata float f = [[user myFloat] floatValue];. La stessa cosa vale per il booleano, esso viene anche memorizzato in un NSNumber. Così, quando si tenta di accedervi si otterrà indietro un NSNumber che è necessario chiamare BOOL b = [[user isMyBool] boolValue]; per ottenere la parte posteriore primitiva.

La stessa cosa vale il contrario, quando si impostano myFloat e myBool, è necessario memorizzare al loro interno un NSNumber, per esempio [user setMyFloat:[NSNumber numberWithFloat:f]]; e [user setMyBool:[NSNumber numberWithBool:b]];.

Per utilizzare questo approccio si dovrebbe cambiare i vostri ultimi due oggetti da

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

, ma si può mantenere la @dynamic per entrambi.

Implementazione proprie getter e setter:
Per comodità, si consiglia l'oggetto "utente" per ottenere e impostare il tipo primitivo, galleggiante e BOOL, direttamente. In questo caso si dovrebbe tenere le proprietà come galleggiante e bool e nel file di implementazione (.m) rimuovere le linee @dynamic per myFloat e myBool.

Per implementare il getter e setter è necessario conoscere un po 'di KVC / KVO e Core Data. In breve: è necessario comunicare al sistema quando si sta per accedere e modificare una proprietà e quando yo u è fatto l'accesso o la modifica, poiché Core Data non lo farà per voi. Tra la "accederà / cambiamento" e "ha fatto l'accesso / cambiamento" sei libero di recuperare o modificare le proprietà. Un altro avvertimento è che Core Data ancora non può salvare l'BOOL e galleggiare direttamente, quindi hanno bisogno di essere confezionati in e non imballati da NSNumbers quando ottiene e l'impostazione.

Inoltre, non è possibile chiamare o [self setValue:ForKey:]; [self valueForKey:@""]; perché questo causerebbe il metodo si è in chiamare se stessa e si gettano in un ciclo infinito. Core Data risolve questo caso d'uso, consentendo di ottenere e impostare il valore senza colpire la propria implementazione chiamando [self setPrimitiveValue:ForKey:] e [self primiveValueForKey:]. Nota: primiteValueForKey non ha nulla a che fare con tipi primitivi (int, float, BOOL) ma è solo il nome dei metodi da utilizzare per ottenere e valori impostati in Core Data direttamente.

L'applicazione per il vostro galleggiante e BOOL sarebbe simile a questa:

- (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"];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top