Я знаю, что могу расширить класс (например, класс фреймворка) с помощью категорий, но возможно ли, чтобы класс, для которого вы не контролируете исходный код, реализовывал один из ваших пользовательских протоколов? Я не только хочу, чтобы он отвечал на определенные сообщения, если они отправлены экземпляру, но также, в идеале, хочу, чтобы объекты этого класса возвращали true при проверке типа во время выполнения при запросе протокола.
Можно ли динамически реализовать протокол в Objective-C?
Ответы (2)
Вы можете определить категорию, которая соответствует протоколу, поэтому вы должны сделать что-то вроде:
@interface UIWebView (MyGreatExtensions) <UITableViewDelegate>
@end
@implementation UIWebView (MyGreatExtensions)
- (CGFloat)tableView: (UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
return 42.0;
}
// ...
@end
Небольшой пограничный случай, который следует учитывать, заключается в том, что если кто-то другой попытается сделать то же самое (например, сторонняя платформа также добавит протокол через категорию), вы не можете гарантировать, что ваш будет использоваться версия (и, конечно же, они не могут).
Подробнее об этом подходе от Марка Далримпла.
Я думаю, это возможно. Вы можете легко создавать динамические прокси-серверы в Objective-C (именно так NSUndoManager делает свое волшебство), перезаписывая метод forwardInvocation: NSObject, перехватывая все нераспознанные сообщения, на которые мог бы ответить разработчик протокола. Я никогда не делал этого сам, поэтому может быть более элегантный способ сделать это.
Кроме того, чтобы обмануть проверки времени выполнения и заставить их согласиться с тем, что ваш объект действительно реализует протокол, вы можете переопределить метод класса NSObject соответственно:
+ (BOOL)conformsToProtocol:(Protocol *)aProtocol {
if (aProtocol == @protocol(MyDynamicallyImplementedProtocol))
return YES;
return [super conformsToProtocol:aProtocol];
}
Может быть больше методов, которые вам нужно переопределить, одним из примеров может быть instancesRespondToSelector: NSObject: и методы resolve*:. Изучите класс NSObject чтобы узнать больше.