2010-02-13 68 views
4

我创建了一个包装UITextView并添加了一些UI元素的类。我希望新类的API与UITextView相同,因此我使用消息转发(下面列出)来在封装的文本视图和委托之间中继消息。在做邮件转发时避免编译器警告

令人烦恼的是,编译器针对我的转发类的实例发出方法调用的警告。例如,将用于下面的行中产生一个错误:

[aMyTextView setContentOffset:CGPointZero animated:YES]; 

所以我不得不声明并创建“手动转发”用于这些方法中,这违背了使用消息转发的全部目的的实现。

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated 
{ 
    [_textView setContentOffset:contentOffset animated:animated]; 
} 

我知道避过这是使用的performSelector:方法之一的常用方法,但是这是一个)累赘时,一些参数不是NSObjects(虽然Erica Sadun's extensions是一个很大的帮助),B)再次,完全违背了创建透明包装的意图。

(子类UITextView中也出了问题,因为我需要插入文本视图下方的意见。)

有没有办法来解决这个问题?

类的所有相关部分的清单:

@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 

回答

4

声明一个类,它提供了你要转发的方法的方法声明:

@interface MyTextField (ImGonnaLetYouFinishButFirstImForwardingThese) 
... methods you want to forward here ... 
@end 

无需提供@implementation。

请注意,这是一个相当不典型的模式。不公平,非常。应该没有理由不能继承子类。你说子类化UITextView也是不可能的,因为我需要在文本视图下插入视图,但事实并非如此。


如果我继承的UITextField,我可以做 与其他意见是将它们 添加为子视图,这意味着他们将 在文本字段的顶部。我想我 可以修改drawRect:...你会建议什么 ?或者你有什么 你的袖子呢?

如果您需要一个组,请创建一个适当管理各种子视图的UIView子类,不需要转发。然后,您可以按自己的喜好订购视图。

转发使用极少。在那条路上是疯狂的。这听起来好像你的设计有点杂草,但没有足够的信息来真正地说出更具体的东西。

+0

您的解决方案:很好,但更好,不必声明方法,只需转发它们,无论它们是什么。 子类化:我想用一些元素来组合实际的文本字段,其中至少有一个元素必须出现在*文本字段下。如果我继承UITextField,那么我只能将其作为子视图添加到其他视图中,这意味着它们将位于文本字段的顶部。我想我可以修改drawRect:...这是你会建议的吗?或者你有什么袖子? – Felixyz 2010-02-14 00:44:15

+0

但是,当你的意思是,你们如何在没有警告和警告的情况下纠正转发?转发非常活跃。至于子类化,你可以在你的子类中做任何你在自定义类中做的事情。 – bbum 2010-02-14 03:23:10

+0

你当然是对的。如果我做出这些警告,那么所有其他警告都会消失,这并不好。所以你的协议解决方案似乎是最好的。子类本身不能放置视图(根据绘制顺序),因为该视图将是子视图,并且总是在父视图之上分层。对? – Felixyz 2010-02-14 03:28:27

0

简单的解决方案是使用动态打字并声明aMyTextViewid,警告将消失。

+0

正确,但如果发送了错误的方法,则会在运行时发生故障。就我个人而言,我仍然想知道OP为什么认为子类化是不可能的。 :) – bbum 2010-02-14 00:28:35