Знам, че мога да разширя клас (например рамков клас), използвайки категории, но възможно ли е клас, за който не контролирате изходния код, да внедри един от вашите персонализирани протоколи? Не само искам да отговаря на определени съобщения, ако бъдат изпратени до екземпляр, но също така, в идеалния случай, искам обектите от този клас да връщат 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 conformsToProtocol: така:
+ (BOOL)conformsToProtocol:(Protocol *)aProtocol {
if (aProtocol == @protocol(MyDynamicallyImplementedProtocol))
return YES;
return [super conformsToProtocol:aProtocol];
}
Може да има повече методи, които трябва да замените, един пример биха били instancesRespondToSelector: и методите resolve*: на NSObject. Разгледайте NSObject референция за клас, за да разберете повече.