363 Stimmen

Ausnahme, die in den von NSOrderedSet generierten Accessors ausgelöst wird

In meiner Lion-Anwendung habe ich dieses Datenmodell:

enter image description here

Die Beziehung subitems innerhalb Item ist bestellt .

Xcode 4.1 (Build 4B110) hat für mich die Datei Item.h , Item.m , SubItem.h y SubItem.h .

Hier ist der Inhalt (automatisch generiert) von Item.h :

#import <Foundation/Foundation.h>

#import <CoreData/CoreData.h>

@class SubItem;

@interface Item : NSManagedObject {
@private
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSOrderedSet *subitems;
@end

@interface Item (CoreDataGeneratedAccessors)

- (void)insertObject:(SubItem *)value inSubitemsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromSubitemsAtIndex:(NSUInteger)idx;
- (void)insertSubitems:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeSubitemsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInSubitemsAtIndex:(NSUInteger)idx withObject:(SubItem *)value;
- (void)replaceSubitemsAtIndexes:(NSIndexSet *)indexes withSubitems:(NSArray *)values;
- (void)addSubitemsObject:(SubItem *)value;
- (void)removeSubitemsObject:(SubItem *)value;
- (void)addSubitems:(NSOrderedSet *)values;
- (void)removeSubitems:(NSOrderedSet *)values;

@end

Und hier ist der (selbst erstellte) Inhalt von Item.m :

#import "Item.h"
#import "SubItem.h"

@implementation Item

@dynamic name;
@dynamic subitems;

@end

Wie Sie sehen können, ist die Klasse Item bietet eine Methode namens addSubitemsObject: . Leider, wenn Sie versuchen, es auf diese Weise zu verwenden:

Item *item = [NSEntityDescription insertNewObjectForEntityForName:@"Item" inManagedObjectContext:self.managedObjectContext];
item.name = @"FirstItem";

SubItem *subItem = [NSEntityDescription insertNewObjectForEntityForName:@"SubItem" inManagedObjectContext:self.managedObjectContext];

[item addSubitemsObject:subItem];

dieser Fehler auftreten:

2011-09-12 10:28:45.236 Test[2002:707] *** -[NSSet intersectsSet:]: set argument is not an NSSet

Können Sie mir helfen?

Aktualisierung:

Nach nur 1.787 Tagen seit meiner Fehlermeldung schrieb mir Apple heute (1. August 2016) Folgendes: "Bitte überprüfen Sie dieses Problem mit dem neuesten iOS 10 Beta-Build und aktualisieren Sie Ihren Fehlerbericht unter bugreport.apple.com mit Ihren Ergebnissen." . Hoffen wir, dass dies der richtige Zeitpunkt ist :)

18voto

Owen Godfrey Punkte 3341

Ich habe den Fehler lokalisiert. Er tritt auf in willChangeValueForKey:withSetMutation:usingObjects: .

Dieser Aufruf setzt eine Kette von Benachrichtigungen in Gang, die schwer nachzuvollziehen sein kann, und natürlich können Änderungen an einem Responder Auswirkungen auf einen anderen haben, weshalb ich vermute, dass Apple nichts unternommen hat.

Es ist jedoch in Ordnung in Set und seine nur die Set-Operationen auf einem OrderedSet, die Fehlfunktion. Das bedeutet, dass es nur vier Methoden gibt, die geändert werden müssen. Daher habe ich lediglich die Set-Operationen in ihre entsprechenden Array-Operationen umgewandelt. Diese funktionieren perfekt und verursachen nur minimalen (aber notwendigen) Overhead.

Wenn Sie Objekte hinzufügen und eines der Objekte bereits existiert, wird es entweder nicht hinzugefügt oder an das Ende der geordneten Liste verschoben (ich weiß nicht, was). In beiden Fällen wird der erwartete geordnete Index des Objekts zum Zeitpunkt der Ankunft bei didChange ist anders als erwartet. Dies kann die Anwendungen einiger Leute stören, aber meine ist davon nicht betroffen, da ich immer nur neue Objekte hinzufüge oder ihre endgültige Position bestätige, bevor ich sie hinzufüge.

- (void)addChildrenObject:(BAFinancialItem *)value {
    if ([self.children containsObject:value]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:self.children.count];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] addObject:value];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)removeChildrenObject:(BAFinancialItem *)value {
    if (![self.children containsObject:value]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:[self.children indexOfObject:value]];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] removeObject:value];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)addChildren:(NSOrderedSet *)values {
    if ([values isSubsetOfOrderedSet:self.children]) {
        return;
    }
    NSIndexSet * indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.children.count, values.count)];
    [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] unionOrderedSet:values];
    [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexSet forKey:ChildrenKey];
}

- (void)removeChildren:(NSOrderedSet *)values {
    if (![self.children intersectsOrderedSet:values]) {
        return;
    }
    NSIndexSet * indexSet = [self.children indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [values containsObject:obj];
    }];
    [self willChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
    [[self primitiveValueForKey:ChildrenKey] minusOrderedSet:values];
    [self didChange:NSKeyValueChangeRemoval valuesAtIndexes:indexSet forKey:ChildrenKey];
}

Natürlich gibt es eine einfachere Lösung, die wie folgt aussieht;

- (void)addChildrenObject:(BAFinancialItem *)value {
    if ([self.children containsObject:value]) {
        return;
    }
    [self insertObject:value inChildrenAtIndex:self.children.count];
}

- (void)removeChildrenObject:(BAFinancialItem *)value {
    if (![self.children containsObject:value]) {
        return;
    }
    [self removeObjectFromChildrenAtIndex:[self.children indexOfObject:value]];
}

- (void)addChildren:(NSOrderedSet *)values {
    if ([values isSubsetOfOrderedSet:self.children]) {
        return;
    }
    [self insertChildren:values atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.children.count, values.count)]];
}

- (void)removeChildren:(NSOrderedSet *)values {
    if (![self.children intersectsOrderedSet:values]) {
        return;
    }
    [self removeChildrenAtIndexes:[self.children indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [values containsObject:obj];
    }]];
}

11voto

Nicolas Manzini Punkte 8083

En Apple docs Zu vielen Beziehungen sagt: Sie sollten auf die stellvertretende veränderbare Menge oder geordnete Menge mit

NSMutableOrderedSet * set = [managedObject mutableOrderedSetValueForKey:@"toManyRelation"];

Durch die Änderung dieser Menge werden Beziehungen zu Ihrem verwalteten Objekt hinzugefügt oder entfernt. Der Zugriff auf die veränderbare geordnete Menge über den Accessor mit der Notation [ ] oder . ist falsch und wird fehlschlagen.

9voto

Danik Punkte 93

Erhielt den gleichen Fehler, @LeeIII Lösung arbeitete für mich (danke!). Ich schlage vor, es leicht zu ändern:

  • Verwenden Sie die Objective-C-Kategorie, um die neue Methode zu speichern (damit wir unsere Methode nicht verlieren, wenn Item erneut erzeugt wird).
  • prüfen, ob wir bereits eine veränderbare Menge haben

Inhalt der Item+category.m :

#import "Item+category.h"

@implementation Item (category)

- (void)addSubitemsObject:(SubItem *)value {
    if ([self.subitems isKindOfClass:[NSMutableOrderedSet class]]) {
        [(NSMutableOrderedSet *)self.subitems addObject:value];
    } else {
        NSMutableOrderedSet* tempSet = [NSMutableOrderedSet orderedSetWithOrderedSet:self.subitems];
        [tempSet addObject:value];
        self.subitems = tempSet;
    }
}

@end

8voto

Καrτhικ Punkte 3733

Wenn Sie mogenerator verwenden, müssen Sie anstelle von

[parentObject add<Child>sObject:childObject];

einfach verwenden:

[[parent object <child>sSet] addObject:childObject];

7voto

Grouchal Punkte 9729

Ich persönlich habe einfach die Aufrufe der von CoreData generierten Methoden durch direkte Aufrufe der Methode ersetzt, wie in einer anderen Lösung von @Stephan beschrieben:

NSMutableOrderedSet* tempSet = [self mutableOrderedSetValueForKey:@"subitems"];
      [tempSet addObject:value];
[tempSet addObject:value];

Dadurch entfällt die Notwendigkeit von Kategorien, die später mit einer Lösung von Apple für den generierten Code in Konflikt geraten könnten, wenn der Fehler behoben ist.

Das hat den zusätzlichen Vorteil, dass es die offizielle Methode ist!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X