2014-09-23 87 views
2

我知道互聯網上有很多關於這個問題的信息,但我被卡住了。我有我需要自定義我的UITextFields的應用程序。例如,我需要在編輯開始時更改邊框顏色,或者需要限制可以在不同文本字段中設置多少個字符。我還需要在幾個文本字段中的圖像,這些圖像必須在左側縮進。爲了做到這一點,我決定製作自定義的UITextField類(以繼承UITextField)。我從UITextField(實現<UITextFieldDelegate>)創建了新班級。在該課程中,我使用self.delegate = self(這在互聯網上廣泛使用,人們說它正在工作),所以我可以在我的自定義類中實現shouldChangeCharactersInRangetextFieldShouldBeginEditing。我的問題是,在此配置中,我收到無限循環並重新啓動應用程序(請參閱my question)。這來自self.delegate = self。我知道在某些情況下,我可以使用observer,但在這種情況下,我可以在班級中執行shouldChangeCharactersInRange嗎? 如果我不以這種方式實現我的課,並將我的文本字段委託給我的視圖控制器。我必須在我的視圖控制器類中實現所有這些方法,在我看來這是非常難看的解決方案。如何正確地在iOS中繼承UITextField?

所以我的問題是如何正確實現UITextField子類?

P.S.我想我是以錯誤的方式去做的,但我無法弄清楚哪一個是正確的。

編輯:

這裏是我的代碼:

MyCustomTextField.h

@interface MyCustomTextField : UITextField 

@property (nonatomic) int maxSymbols; 
@property (nonatomic) int leftIndent; 

@end 

MyCustomTextField.m

@interface MyCustomTextField() <UITextFieldDelegate> 

@end 

@implementation MyCustomTextField 
- (id)initWithCoder:(NSCoder *)aDecoder{ 
    if (self = [super initWithCoder:aDecoder]) { 

     self.delegate = self; 

     self.clipsToBounds = YES; 
     [self setLeftViewMode:UITextFieldViewModeAlways]; 

     UIImageView *imageView1 = [[UIImageView alloc] 
            initWithFrame:CGRectMake(0, 0, 37, 20)]; 
     imageView1.image = [UIImage imageNamed:@"otp_back"]; 
     self.leftView = imageView1; 

    } 
    return self; 
} 

- (CGRect) leftViewRectForBounds:(CGRect)bounds { 

    CGRect textRect = [super leftViewRectForBounds:bounds]; 
    textRect.origin.x = 5; 
    return textRect; 
} 

這種方法也用於檢查最大長度:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{ 

    // Restrict number of symbols in text field to "maxSymbols" 
    NSUInteger oldLength = [textField.text length]; 
    NSUInteger replacementLength = [string length]; 
    NSUInteger rangeLength = range.length; 

    NSUInteger newLength = oldLength - rangeLength + replacementLength; 

    BOOL returnKey = [string rangeOfString: @"\n"].location != NSNotFound; 

    return newLength <= (int)_maxSymbols || returnKey; 
} 

當我去到文本字段,並開始從我收到的無限循環和退出與錯誤訪問模擬器的虛擬鍵盤輸入。這很奇怪,因爲如果鍵盤是數字或密碼類型,或者如果我從Mac鍵盤輸入,我沒有收到問題。

+0

你能表現出一些實際的代碼?很多事情取決於你什麼時候說什麼。 – matt 2014-09-23 15:10:48

回答

2

我不會在您的自定義UITextField中將代理設置爲self,它並不是很整潔。 我會做什麼只是有一個屬性或版本的方法,您可以調用您的控制器時,您收到代表電話。

基本上在你看來什麼地方控制器:

- (void)viewDidLoad{ 
    .... 
    self.textField = [[CustomTextField alloc] init]; 
    self.textField.delegate = self; 

} 

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ 
    self.textField.editMode = YES; 
} 

而在你CustomTextField

-(void)setEditMode:(BOOL)edit{ 
    if(edit){ 
     self.layer.borderColor=[[UIColor redColor]CGColor]; 
     self.layer.borderWidth= 1.0f; 
    } 
} 
1

對於編輯的開始和結束,你有becomeFirstResponderresignFirstResponder。這是最好的地方。重寫,不要忘記打電話給超級。對於輸入操作,你必須檢查文檔。有兩種方式,通過通知和子類。兩者都提供不同程度的靈活性。

+0

我是iOS開發新手,能否給我提供一個解決方案示例的鏈接?我明白,當我編輯時,我改變FirstResponder,從這一點你的解決方案聽起來很好,但我不知道該怎麼做。 – new2ios 2014-09-24 07:50:20

+0

@ new2ios我沒有特別的鏈接,因爲它非常基本,並且在文檔中有所涉及,但你可以檢查它是如何在FlatUIKit中完成的:https://github.com/Grouper/FlatUIKit/blob/master/Classes/ios/ FUITextField.m – Andy 2014-09-24 09:43:34

+0

10x爲鏈接 – new2ios 2014-09-24 09:55:30

4

我不同意在視圖控制器中始終設置委託。當許多不同的視圖控制器共享相同的文本字段行爲時,使用UITextField本身作爲代理(如更簡潔的代碼)有一些明顯的優勢。

在iOS 8中,自我委託引用循環似乎是「固定的」。但是,對於那些針對iOS的7和下面,我們用一個代理對象,以繞過環:

InputTextProxy.h:

@interface InputTextProxy : NSObject <UITextFieldDelegate> 
@property (weak, nonatomic) id<UITextFieldDelegate> proxiedDelegate; 
@end 

InputTextProxy.m:

#import "InputTextProxy.h" 

@implementation InputTextProxy 

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{ 
    return [self.proxiedDelegate textFieldShouldReturn:textField]; 
} 

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    return [self.proxiedDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string]; 
} 

@end 

您可以添加更多的回調如有必要,我們只使用上述兩個。

現在,在你的子類MyCustomTextField.m創建一個屬性:

@property (strong, nonatomic) InputTextProxy *inputProxy; 

- (InputTextProxy *)inputProxy 
{ 
    if (!_inputProxy) 
     _inputProxy = [[InputTextProxy alloc] init]; 
    return _inputProxy; 
} 

使用此設置您的委託:

self.delegate = self.inputProxy; 
self.inputProxy.proxiedDelegate = self; 
+0

我同意你的意見@e_x_p,但那是唯一的工作解決方案(有時會發生循環)。還有一些情況需要在'ViewController'中的'edit'事件中管理額外的東西。我肯定會嘗試你的解決方案。 – new2ios 2015-08-04 16:19:37

+0

我忍不住寫了15+視圖控制器的相同代碼...希望它能幫助你@ new2ios – 2015-08-05 06:58:23

+0

因爲這是唯一的解決方案,我已經編寫了VC,@e_x_p 2.我會盡量用你的方式我的下一個項目或當我有時間將我的應用程序快速移動時。 – new2ios 2015-08-05 09:43:23