2013-12-18 3 views
7

Dies ist ein Geheimnis:Core Data: setPrimitiveValue: forKey: benimmt sich wirklich seltsam

ich setPrimitiveValue:forKey: auf einem NSManagedObject bin aufrufen. Der Schlüssel ist ein legitimes, beständiges, modelliertes Attribut des Objekts. SetPrimitiveValue: forKey: schlägt jedoch fehl und setzt oft den Wert für ein anderes, beliebiges Attribut. Die Dokumentation sagt, dass dieses Verhalten erwartet wird, wenn setPrimitiveValue:forKey: für einen nicht modellierten Schlüssel aufgerufen wird. Es scheint also, Core Data denkt, dass der Schlüssel nicht modelliert ist.

Der seltsame Teil:

Wenn der Schlüssel als Stringliteral fest einprogrammiert ist, wird der Grundwert in der Tat erfolgreich gesetzt. Es schlägt nur fehl, wenn der Schlüssel eine Variable ist. Die von mir verwendete Variable wird vom keyPath-Argument von observeValueForKeyPath:ofObject:change:context:

übergeben. Die Variable keyPath ist mit dem Zeichenfolgenliteral identisch. isEqual: gibt true zurück und die Hashwerte sind gleich. Die Variable keyPath ist vom Typ __NSCFString. Weiß jemand, warum sich setPrimitiveValue:forKey: anders verhalten würde? (Dieses Verhalten ist auf OS X 10.9.1)


Ein Update mit besseren Informationen:

Der Schlüssel abgestürzten in einen String aus einer Datei auf der Festplatte geladen zurückverfolgt. Das folgende Beispiel ist ein Einzelfall. Wenn der Attributstring "mainAttr" auf Platte geschrieben und wieder eingelesen wird, setzt setPrimitiveValue:forKey: den Wert für das falsche Attribut, nicht "mainAttr".

Kerndatenobjekt:

@interface Boo : NSManagedObject 
@property (nonatomic, retain) NSNumber * mainAttr; 
@property (nonatomic, retain) NSNumber * attr1; 
@property (nonatomic, retain) NSNumber * attr2; 
@property (nonatomic, retain) NSNumber * attr3; 
@end 

-

#import "Boo.h" 

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
      NSManagedObjectContext *context = managedObjectContext(); 
    NSString *key = @"mainAttr"; 

    // write to disk, read back in 
    NSString *path = [@"~/Desktop/test.txt" stringByExpandingTildeInPath]; 
    [key writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL]; 
    key = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; 

    Boo *boo = [NSEntityDescription insertNewObjectForEntityForName:@"Boo" inManagedObjectContext:context]; 
    [boo setPrimitiveValue:@(5) forKey:key]; 

    NSLog(@"Boo: %@", boo); 
    } 
    return 0; 
} 
+0

Wir haben ein ähnliches Verhalten auf iOS gesehen, mit einem "generischen" Validierungsfehler beim Speichern fehlgeschlagen. Ihre Frage bringt eine interessante Sichtweise, warum dies geschieht. –

+2

Ich weiß es nicht, aber ich wäre daran interessiert, Code von 'observeValueForKeyPath: ofObject: change: context:' zu sehen, wo das Problem auftritt. –

+0

Kannst du das in ein Testprojekt einbauen? –

Antwort

1

Sie müssen die folgenden drei Aussagen den Wert einzustellen. Versuch es.

[self willChangeValueForKey:key]; 
[boo setPrimitiveValue:@(5) forKey:key]; 
[self didChangeValueForKey:key];