Есть ли способ поймать нажатие клавиши возврата, когда UITextField является первым респондентом без использования делегата? - PullRequest
3 голосов
/ 10 июля 2011

Я хочу создать подкласс UITextField, который имеет предопределенное действие при нажатии клавиши возврата, но во всех остальных отношениях ничем не отличается от UITextField. Изменить: я бы предпочел, чтобы делегат работал как обычно - один из способов сделать это - создать делегат, который отправляет textFieldshouldReturn: подклассу, а другие сообщения - фактическому делегату, но я бы предпочел оставить его для одного объекта если возможно.

Ответы [ 4 ]

6 голосов
/ 27 сентября 2014

Это супер просто и вот как:
В вашем подклассе UITextField добавьте метод целевого действия для UIControlEventEditingDidEndOnExit event

[self addTarget:self action:@selector(returnPressed) forControlEvents:UIControlEventEditingDidEndOnExit];

Теперь селектор будет вызываться при каждом нажатии клавиши возврата.

0 голосов
/ 24 июля 2012

Решение состоит в том, чтобы ваш подкласс UITextField имел собственный закрытый делегат, который вы вставляете между вашим текстовым полем и его «обычным» делегатом.

Вы должны создать свой закрытый делегат в ваших initWithFrame: и initWithCoder: методови использовать его в качестве вашего делегата.Свойство strong / retain необходимо, поскольку свойство делегата UITextField не сохраняет его содержимое.

@interface MyTextFieldPrivateDelegate: NSObject<UITextFieldDelegate>
@end

@interface MyTextField()
@property (nonatomic, strong) MyTextFieldPrivateDelegate *privateDelegate;
@end

@implementation MyTextField
@synthesize privateDelegate;

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.privateDelegate = [[MyTextFieldPrivateDelegate alloc] init];
        self.delegate = self.privateDelegate;
    }
    return self;
}

Вы должны переопределить setDelegate: для вставки вашего частного делегата между ними.

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

@implementation MyTextFieldPrivateDelegate
@synthesize delegate;
@end

@implementation MyTextField
- (void)setDelegate:(id<UITextFieldDelegate>)delegate
{
    if (delegate == self.privateDelegate) {
        [super setDelegate:delegate];
    } else {
        self.privateDelegate.delegate = delegate;
    }
}
@end

Ваш личный делегат будет реализовывать вашу пользовательскую textFieldShouldReturn: реализацию и все другие методы UITextFieldDelegate

@implementation MyTextFieldPrivateDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
    // ...
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if ([self.delegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) {
        return [self.delegate textFieldShouldBeginEditing:textField];
    }

    return YES;
}

// etc.

@end
0 голосов
/ 22 марта 2014

Я думаю, что Гвендал был на правильном пути, поэтому я взял ее ответ и расширил его. Все, что вам нужно сделать, это включить приведенный ниже код в свой проект, а затем в Интерфейсном Разработчике изменить класс с UITextField на ARTextField (AR = Automatic Resigner), чтобы получить желаемое поведение.

Я все еще пытаюсь решить, должно ли объявление свойства userDelegate быть сильным или слабым ...

ARTextField.h Файл:

//
//  ARTextField.h
//
//  Created by Terry Grossman on 3/21/14.
//

#import <UIKit/UIKit.h>

@interface ARTextField : UITextField <UITextFieldDelegate>

@property (nonatomic, strong) NSObject<UITextFieldDelegate> *userDelegate;

@end

ARTextField.m Файл:

//
//  ARTextField.m
//
//  Created by Terry Grossman on 3/21/14.
//

#import "ARTextField.h"

@implementation ARTextField


- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {

        [super setDelegate:self];
    }
    return self;
}

-(id) initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self)
    {
        [super setDelegate:self];
    }

    return self;
}

-(void) awakeFromNib
{
    [super awakeFromNib];
    [super setDelegate:self];
}


// if user wants a delegate, we stash it.
- (void)setDelegate:(id<UITextFieldDelegate>)delegate
{
    if (delegate != self)
    {
        self.userDelegate = delegate;
    }
}

- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    [textField resignFirstResponder];

    if (self.userDelegate != nil && [self.userDelegate respondsToSelector:@selector(textFieldShouldReturn:)])
    {
        return [self.userDelegate textFieldShouldReturn:textField];
    }

    return NO;
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textFieldShouldBeginEditing:)]) {
        return [self.delegate textFieldShouldBeginEditing:textField];
    }

    return YES;
}


- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)])
    {
        return [self.userDelegate textField:textField shouldChangeCharactersInRange:range replacementString:string];
    }

    return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textFieldShouldEndEditing:)]) {
        return [self.userDelegate textFieldShouldEndEditing:textField];
    }

    return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textFieldShouldClear:)]) {
        return [self.userDelegate textFieldShouldClear:textField];
    }

    return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textFieldDidEndEditing:)]) {
        [self.userDelegate textFieldDidEndEditing:textField];
    }
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (self.userDelegate != nil &&  [self.userDelegate respondsToSelector:@selector(textFieldDidBeginEditing:)]) {
        [self.userDelegate textFieldDidBeginEditing:textField];
    }

}


@end
0 голосов
/ 10 июля 2011

Вы можете переопределить метод textFieldShouldReturn в своем подклассе. И этот класс будет делать все то, что делает обычный UItextField.

UPDATE

@interface MyTextField : UITextField {

}

@end



@implementation MyTextField


- (CGRect)textRectForBounds:(CGRect)bounds {

    return CGRectInset(bounds, 10, 0);
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return CGRectInset(bounds, 10, 0);
}

- (void) drawRect:(CGRect)rect{
    [super drawRect:rect];
}



-(BOOL)textFieldShouldReturn:(UITextField*)textField {

 //write you code here to capture the return key.
 //Make sure to change textfield's class from interface builder if you are using interfce builder or initialize by code.
 }
@end
...