Frage

Dies ist meine erste Zeit mit dem Versuch, beide zu verwenden, ARC und Core Data.Ich kann nicht scheinen, um herauszufinden, warum mein code zum Absturz zu bringen.

in der .h ich habe:

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

in der .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.

Im Grunde, wenn ich versuche, einen anderen Datentyp als string, erhalte ich die EXEC-crash auf die jeweilige Zeile.Wenn ich strings für alles, es ist in Ordnung.In meinem.xcdatamodeld-Datei habe ich myFloat set zu SCHWEBEN und myBool set 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
War es hilfreich?

Lösung

Sie können nicht verwenden @dynamic für primitive Typen (wie float und BOOL) da Core Data keine Implementierungen für Sie.

Also der Grund, warum Ihr code abstürzt, ist, weil, wenn Sie verwenden @dynamic Sie sagen dem compiler "ich verspreche, dass eine Implementierung für diese Getter und setter werden zur Laufzeit".Aber da Core Data nicht erstellen Ihnen dann Ihr code versucht, um Methoden aufzurufen, die nicht existiert.

Stattdessen gibt es zwei Dinge, die Sie tun könnten:Verwenden Sie eine NSNumber für beide BOOL und der Schwimmer oder implementieren Ihre eigenen Getter und setter.

Mit NSNumber:
Core Data verwendet nur die Objekte und nicht die primitive, aber Sie können angeben, boolean oder float in die Modell.Wenn Sie anrufen [user myFloat] erhalten Sie tatsächlich eine NSNumber zurück mit der float-Wert drin.Um den Zugriff auf die primitive, rufen Sie anschließend float f = [[user myFloat] floatValue];.Das gleiche gilt für die Boolesche, wird es auch gespeichert in eine NSNumber.Also, wenn Sie versuchen, darauf zuzugreifen, Sie zurück erhalten eine NSNumber, die Sie aufrufen müssen BOOL b = [[user isMyBool] boolValue]; um die primitiven zurück.

Das gleiche geht auch Umgekehrt, wenn die Einstellung myFloat und myBool, die Sie benötigen, speichern Sie Sie in einer NSNumber, z.B. [user setMyFloat:[NSNumber numberWithFloat:f]]; und [user setMyBool:[NSNumber numberWithBool:b]];.

Um diesen Ansatz verwenden würden Sie ändern müssen Ihre letzten beiden Eigenschaften

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

aber können Sie halten die @dynamic für beide von Ihnen.

Implementieren Sie eigene Getter und setter:
Für Ihre Bequemlichkeit, können Sie wollen, dass Ihre "Benutzer" - Objekt zum abrufen und festlegen von den primitiven Typen, float und BOOL, direkt.In diesem Fall sollten Sie die Eigenschaften float und bool und in Ihrer Implementierungsdatei (.m) entfernen Sie die @dynamic Linien für myFloat und myBool.

Implementieren Sie die getter und setter müssen Sie wissen, ein wenig über KVC/KVO und Core Data.In kurz:Sie müssen dem system mitteilen, wenn Sie über Zugriff auf oder ändern Sie eine Eigenschaft, und wenn Sie fertig sind, zugreifen auf oder ändern Sie, da Core Data wird es nicht tun für Sie.Zwischen den "Zugang/ändern" und "hast Zugriff/ändern" Sie sind frei, abrufen oder ändern Sie die Eigenschaften.Eine weitere Einschränkung ist, dass die Core Daten noch nicht speichern kann, BOOL-und schweben direkt, so, die Sie benötigen, um verpackt in und unverpackt aus NSNumbers, wenn das abrufen und setzen.

Weiter kann man das auch nicht nennen [self setValue:ForKey:]; oder [self valueForKey:@""]; weil, dass verursachen würde die Methode, die Sie in sich selbst und werfen Sie in eine unendliche Schleife.Core Data löst diesen Fall, indem Sie get-und set die Wert, ohne auf Ihre eigene Umsetzung durch den Aufruf [self setPrimitiveValue:ForKey:] und [self primiveValueForKey:]. Hinweis: primiteValueForKey hat nichts zu tun mit primitiven Typen (int, float, BOOL), sondern nur die Namen der Methoden, die Sie verwenden, um get-und set-Werte in Core-Daten direkt.

Die Umsetzung für float und BOOL Aussehen würde etwas wie dieses:

- (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"];
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top