2015-08-03 1 views
0

Файл xib в моем проекте OS X содержит представление таблицы, поддерживаемое NSArrayController, которое установлено в . Объект Entity Name (aka Core Data). Когда я отправляю сообщение -add: этому контроллеру массива, возникает исключение, когда генерируется консоль:NSArrayController из NSManagedObject обращается к * массиву * вместо * установленного *

NSManagedObjects объекта Foo не поддерживает -mutableArrayValueForKey: для свойств «баров».

Правильно! Вместо этого NSManagedObjects поддерживает -mutableSetValueForKey :, и я всегда думал, что NSArrayController знал об этом и вел себя соответственно - находясь в . Объект Entity Name, я ожидаю, что он отправит -mutableSetValueForKey: в мой объект Foo, а не -mutableArrayValueForKey :. Из документации:

Обычно коллекция представляет собой массив, если контроллер управляет отношением управляемого объекта (см. NSManagedObject), коллекция может быть набором.

Если я «подделать», добавив следующий метод в мой класс Foo, он предотвращает исключение из воспитывается, но, конечно, это действительно не работает:

- (NSMutableArray*)mutableArrayValueForKey:(NSString*)key { 
    [self willAccessValueForKey:key]; 

    NSMutableArray* result = [[[self valueForKey:key] allObjects] mutableCopy] ; 

    [self didAccessValueForKey:key]; 
    return result; 
} 

Что может быть Неправильно здесь? Я проверил «режим» этого контроллера массива пять раз.

ответ

0

После дополнительных исследований, я думаю, что этот вопрос является частью более сложной проблемы NSOrderedSet, несовместимой с привязками к какао. Этот вопрос: explained here by Tom Fewster:

Однако, как комментирует Рик в комментариях к этому сообщению в блоге, OrderedSetArrayValueTransformer Tom Fewster все еще не решает проблему с добавлением: и удаляет :.

Я поэтому написал очень kludgey сейчас работает обходной путь, подклассификация NSArrayController и переопределение -add: и -remove :. Мои реализации обращаются к материнскому объекту Foo , которому принадлежит коллекция баров (баров). Обычно этот объект недоступен для контроллера массива. Я получаю его, следуя обратной зависимости от первого объекта Bar, который работает, потому что в этом конкретном приложении Foo всегда должен иметь по крайней мере один бар. В противном случае нам понадобится отдельный «провод» (свойство, или, желательно, привязка, который Interface Builder не поддерживает) к объекту Foo. Arghhhh.

Обращаем ваше внимание, что следующий код является очень плохим решением проблемы. Надеюсь, это может вдохновить кого-то опубликовать лучшую идею; но лучше, чем Ха-ха, не используйте привязки какао и/или основные данные!, потому что мой корабль уже отплыл на этом, особенно в этом конкретном проекте.

Этот код использует методы доступа к коллекции, которые могут не иметь ваши управляемые объекты. Самый простой способ получить их - использовать mogenerator.

@implementation BarArrayController 

- (Foo*)parentObject { 
    Bar* aBar = (Bar*)[[self content] firstObject] ; 
    NSAssert(aBar, @"Cannot have 0 bars") ; 
    Foo* parentObject = aBar.Foo ; 

    return parentObject ; 
} 

- (void)add:(id)sender { 
    NSManagedObject* newObject = [NSEntityDescription insertNewObjectForEntityForName:self.entityName 
                   inManagedObjectContext:self.managedObjectContext] ; 
    Foo* parentObject = [self parentObject] ; 
    [parentObject insertObject:(Bar*)newObject 
       inBarsAtIndex:parentObject.slices.count]; 
} 

- (void)remove:(id)sender { 
    Foo* parentObject = [self parentObject] ; 
    if (parentObject.bars.count > 1) { 
     NSInteger selectedIndex = self.selectionIndex ; 
     if (selectedIndex != NSNotFound) { 
      NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:selectedIndex] ; 
      [parentObject removeBarsAtIndexes:indexSet] ; 
     } 
    } 
    else { 
     NSBeep() ; 
    } 
} 

@end 
Смежные вопросы