我创建了一个包装 UITextView 并添加一些 ui 元素的类。我希望新类的 API 与 UITextView 相同,因此我使用消息转发(如下所列)在包装文本 View 和委托(delegate)之间中继消息。
令人恼火的是,编译器对我的转发类实例的方法调用发出警告。例如,以下行将生成错误:
[aMyTextView setContentOffset:CGPointZero animated:YES];
所以我被迫为这些方法声明和创建“手动转发”实现,这违背了使用消息转发的全部目的。
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
[_textView setContentOffset:contentOffset animated:animated];
}
我知道解决这个问题的通常方法是使用
performSelector:
方法之一,但这是 a) 当某些参数不是 NSObjects 时很麻烦(尽管 Erica Sadun's extensions 有很大帮助),b) 再次,完全违背了创建的意图一个透明的包装。(子类化 UITextView 也是不可能的,因为我需要在文本 View 下方插入 View 。)
有没有办法解决这个问题?
类的所有相关部分的列表:
@interface MyTextField : UIView<UITextViewDelegate>
{
UIImageView* _border;
UITextView* _textView;
UIButton* _clearButton;
NSObject<UITextViewDelegate>* _delegate;
}
@implementation MWTextField
. . .
// Forwards messages in both directions (textView <--> delegate)
#pragma mark Message forwarding
// Protocol messages will only be sent if respondsToSelector: returns YES
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ([_delegate respondsToSelector:aSelector])
return YES;
else
return [super respondsToSelector:aSelector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
// First, try to find it in the UITextView
if ([_textView respondsToSelector:selector])
{
return [_textView methodSignatureForSelector:selector];
}
// Then try the delegate
else if ([_delegate respondsToSelector:selector])
{
return [_delegate methodSignatureForSelector:selector];
}
else
{
return [super methodSignatureForSelector: selector];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
SEL aSelector = [invocation selector];
if ([_textView respondsToSelector:aSelector])
{
[invocation invokeWithTarget:_textView];
}
else if ([_delegate respondsToSelector:aSelector])
{
[invocation invokeWithTarget:_delegate];
}
else
{
[self doesNotRecognizeSelector:aSelector];
}
}
. . .
@end
最佳答案
声明一个类别,该类别提供您要转发的方法的方法声明:
@interface MyTextField (ImGonnaLetYouFinishButFirstImForwardingThese)
... methods you want to forward here ...
@end
无需提供@implementation。
请注意,这是一个相当不典型的模式。不公平,非常。你应该没有理由不能子类化。你说子类化 UITextView 也是不可能的,因为我需要在文本 View 下方插入 View ,但事实并非如此。
如果你需要一个组,创建一个 UIView 子类来适本地管理各种 subview ,不需要转发。然后您可以随意订购 View 。
转发很少使用。沿着这条路走下去的是疯狂。听起来您的设计确实有点杂草丛生,但没有足够的信息来真正说出更具体的内容。
关于objective-c - 在进行消息转发时避免编译器警告,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2259012/