2010-02-13 58 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