приведение объекта типа id к неизвестному типу во время выполнения - PullRequest
2 голосов
/ 01 июля 2011

У меня есть метод, который принимает в качестве строки имя объекта в моей базе данных sqlite, который я пытаюсь упростить, чтобы использовать как можно меньше повторяющегося кода.

здесь у меня есть объект в качестве идентификатора, который яя пытаюсь установить требуемый тип объекта в готовности сделать вызов для вставки строки.

проблема заключается в том, что когда я делаю вызов сущности NSEntityDescription, она все еще имеет идентификатор класса

  id entity;

if ([entityName isEqualToString:@"yadda yadda"]) {

    entity = [EntityYadda class];
}
else if ([entityName isEqualToString:@"blah blah"]) {

    entity = [EntityBlah class];
}
else if ([entityName isEqualToString:@"Foobar"]) {

    entity = [EntityFoobar class];
}

for (int x=0; x<[data count]; x++) {

    entity = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];

Куда я иду не так?

Спасибо

Ответы [ 3 ]

1 голос
/ 01 июля 2011

У меня есть 7 разных сущностей, все с одинаковыми полями, поэтому я пытаюсь динамически назначить требуемый класс сущностей для «сущности», поэтому в моем цикле у меня будет только одна строка, использующая NSEntityDescription и настройки свойств.

Что ж, у вас уже возникла мысль "почему бы не одна сущность с полем флага, обозначающим тип?", И это отличный вопрос, и я очень рекомендую пойти по этому маршруту.

Если по какой-то причине вы не можете этого сделать, вы можете объявить идентичные поля в протоколе, а затем объявить, что все эти 7 объектов соответствуют одному и тому же протоколу. В вашем методе ваше объявление типа будет (вместо id): NSManagedObject<MyCustomProtocol> *.

0 голосов
/ 01 июля 2011

Я не гуру, но, насколько я знаю, есть только 2 способа объявления переменных:

  1. с использованием статической типизации (когда вы объявляете тип вашей переменной: UIView * myview)
  2. с использованием динамической типизации (когда вы объявляете свою переменную с помощью «id»: id myObject)

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

В любом случае вы можете динамически назначать классы, используя NSSClassFromString () избегая длинных операторов if / else или switch.

Более того, вы можете (должны) использовать такие инструменты, как RespondsToSelector: (SEL), чтобы гарантировать, что вы отправите сообщение классу безопасно

0 голосов
/ 01 июля 2011

Почему бы вам не создать typedef:

typedef enum {

EntityTypeYaddaYadda,
EntityTypeBlahBlah,
    EntityTypeFoobar

} EntityType;

Затем выполните переключение:

for (int x=0; x<[data count]; x++) {

switch (entity.entityType){
case EntityTypeYaddaYadda:
{
YaddaYadda *yaddaYaddaObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
... set properties...
}
break;

case EntityTypeBlahBlah:
{
BlahBlah *blahBlahObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
... set properties...
}
break;

case EntityTypeFoobar:
{
Foobar *foobarObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
... set properties...
}
break;
}

Затем сохраните свой контекст:

if (![managedObjectContext save:&error]) {
NSLog(@"Error while saving.");
}

Иногда требуется немного повторения кода, чтобы сделать его читаемым и расширяемым.

...