NSClassFromString не позволит мне устанавливать делегата

Я использую NSClassFromString для alloc viewcontrollers. Но это не позволит мне установить делегата в сам. Действительно ли это возможно?

nibString = @"ViewControllerName";
Class viewControllerClass = NSClassFromString( nibString );
loadedVC = (UIViewController*) [[viewControllerClass alloc] initWithNibName:nibString bundle:nil];
[loadedVC setDelegate:self];

Последняя линия сообщает, что Никакой [email protected] для "UIViewController" не объявляет отборщика 'setDelegate'

Я уверен, ассигную ли я vc через собственность, это будет работать, но я использую этот метод для удобства - хотя, возможно, я должен остановиться, если я могу дать, устанавливает, это - делегат.

Кто-либо может предложить решение?

0
nl ja de

2 ответы

Я предполагаю, что вы объявили loadedVC как это:

UIViewController *loadedVC;

Компилятор только позволит вам послать ему сообщения, что это знает, часть UIViewController @interface . Это - хорошая вещь. Это предотвращает много ошибок периода выполнения. Но иногда вы знаете лучше, чем компилятор, и вы хотите выключить @interface проверка.

Когда вы пытаетесь послать сообщение в ценность типа id , компилятор не проверяет сообщение, потому что , id является универсальным типом, у которого нет никакого @interface . Так бросок loadedVC , чтобы id :

[(id)loadedVC setDelegate:self];

Обратите внимание что, если loadedVC не имеет (или наследует), setDelegate: метод, вы получите ошибку периода выполнения. Если вы хотите проверить на метод сначала, попробуйте это:

if ([loadedVC respondsToSelector:@selector(setDelegate:)]) {
    [(id)loadedVC setDelegate:self];
}

Иначе можно сделать это, создавая протокол, содержащий setDelegate: метод:

@protocol HasDelegate
- (void)setDelegate:(id)delegate;
@end

Тогда можно объявить loadedVC как это, чтобы сказать компилятору, что это соответствует протоколу:

UIViewController *loadedVC;

Теперь компилятор не будет жаловаться, когда вы попытаетесь послать setDelegate: , чтобы loadedVC (даже без броска). Но вы все еще получите ошибку периода выполнения, если loadedVC не будет на самом деле иметь setDelegate: метод.

2
добавлено

У класса UIViewControler нет недвижимости делегата. Обычно вы устанавливаете диспетчера представления как делегата представления, таким образом, setDelegate назвали бы согласно представлению, не диспетчеру.

Если у вас будет диспетчер представления подкласс, который действительно поддерживает делегата, это не будет видимо к компилятору, так как ваша loadedVC ссылка была брошена в UIViewControler. Если это - проблема, есть несколько решений.

1) Можно бросить к классу, используемому или первому суперклассу, который осуществляет делегата.

2) Можно использовать формальный или неофициальный протокол.

3) Можно назвать respondsToSelector: сопровождаемый performSelector:withObject:

и т.д.

1
добавлено