programing

빈 UI 텍스트 필드에서 백스페이스 검색

jooyons 2023. 6. 29. 20:04
반응형

빈 UI 텍스트 필드에서 백스페이스 검색

의 iPhone 키보드에서 Delete/ 키를 눌렀을 때 감지할 수 있는 방법이 있습니까?UITextField그것은 비어 있습니까?가 눌렸을 때는 다음의 경우에만 알고 싶습니다.UITextField비어 있습니다.


@Alex Reynolds의 의견에 따라 텍스트 필드를 작성하는 동안 다음 코드를 추가했습니다.

[[NSNotificationCenter defaultCenter] addObserver:self
          selector:@selector(handleTextFieldChanged:)
              name:UITextFieldTextDidChangeNotification
            object:searchTextField];

되었습니다.handleTextFieldChanged함수가 호출됨). 그러나 빈 필드에서 키를 누를 때는 그렇지 않습니다.아이디어 있어요?


이 질문에 대해 약간의 혼란이 있는 것 같습니다.키를 눌렀을 때 알림을 받고 싶습니다.바로 그겁니다.하지만 해결책은 다음과 같은 경우에도 작동해야 합니다.UITextField이미 비어 있습니다.

스위프트 4:


클래스UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate: AnyObject {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.textFieldDidDelete()
    }

}

구현:

// ViewController.swift

import UIKit

class ViewController: UIViewController, MyTextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // initialize textField
        let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40))

        // set viewController as "myDelegate"
        input.myDelegate = self

        // add textField to view
        view.addSubview(input)

        // focus the text field
        input.becomeFirstResponder()
    }

    func textFieldDidDelete() {
        print("delete")
    }

}

목표-C:


클래스UITextField:

//Header
//MyTextField.h

//create delegate protocol
@protocol MyTextFieldDelegate <NSObject>
@optional
- (void)textFieldDidDelete;
@end

@interface MyTextField : UITextField<UIKeyInput>

//create "myDelegate"
@property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
@end

//Implementation
#import "MyTextField.h"

@implementation MyTextField

- (void)deleteBackward {
    [super deleteBackward];

    if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){
        [_myDelegate textFieldDidDelete];
    }
}

@end

이제 MyTextFieldDelegate를 귀하의 웹 사이트에 추가하십시오.UIViewController 설합다니를 설정합니다.UITextFields 에의 의 대표단.self:

//View Controller Header
#import "MyTextField.h"

//add "MyTextFieldDelegate" to you view controller
@interface ViewController : UIViewController <MyTextFieldDelegate>
@end

//View Controller Implementation
- (void)viewDidLoad {
    //initialize your text field
    MyTextField *input = 
     [[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)];

    //set your view controller as "myDelegate"
    input.myDelegate = self;

    //add your text field to the view
    [self.view addSubview:input];
}

//MyTextField Delegate
- (void)textFieldDidDelete {
    NSLog(@"delete");
}

업데이트: Jacob Caraballo의 답변에서 재정의하는 예를 참조하십시오.-[UITextField deleteBackward].

체크아웃. 특히 삭제 키를 누를 때 항상 호출되는 위임 메서드가 있습니다.간단한 일을 하고 있다면 하위 분류를 고려할 수도 있습니다.UILabel그리고 그것을 적합하게 만드는 것.UIKeyInput프로토콜, SimpleTextInput 및 이 iPhone UIKeyInput 예제에서 수행된 것과 같습니다.참고: 및 관련 항목( 포함)은 iOS 3.2 이상에서만 사용할 수 있습니다.

가능성은 희박하지만 효과가 있을 수 있습니다.필드의 를 0 문자 0 비 0 너 로 설 보 해 정 십 시 오 문 자 공 백 를 필 텍 드 의 ▁try 오 시 ▁the 십 보 ▁a ▁character ▁setting ' ▁space ▁width 해 텍 설 ▁field ▁text\u200B빈 텍스트 필드에서 백스페이스를 누르면 실제로 사용자의 스페이스가 삭제됩니다.그러면 공간을 다시 삽입하면 됩니다.

사용자가 캐럿을 공간 왼쪽으로 이동하는 경우 작동하지 않을 수 있습니다.

다음과 같은 코드:

@interface MyTextField : UITextField
@end

@implementation MyTextField

- (void)deleteBackward
{
    [super deleteBackward];

    //At here, you can handle backspace key pressed event even the text field is empty
}

@end

마지막으로 텍스트 필드의 사용자 정의 클래스 속성을 "내 텍스트 필드"로 변경해야 합니다.

신속한 구현:

import UIKit

// Extend from PinTextFieldDelegate instead of UITextFieldDelegate in your class
protocol PinTextFieldDelegate : UITextFieldDelegate {
    func didPressBackspace(_ textField: PinTextField)
}

class PinTextField: UITextField {

    override func deleteBackward() {
        super.deleteBackward()

        // If conforming to our extension protocol
        if let pinDelegate = self.delegate as? PinTextFieldDelegate {
            pinDelegate.didPressBackspace(self)
        }
    }
}

내가찾다방은보다 더 .subclassㅠㅠㅠㅠ 합니다.조금 이상하기도 하지만 잘 작동합니다.

- (BOOL)textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
        replacementText:(NSString *)text
{
    const char * _char = [text cStringUsingEncoding:NSUTF8StringEncoding];
    int isBackSpace = strcmp(_char, "\b");

    if (isBackSpace == -8) {
       // is backspace
    }

    return YES;
}

비교 결과가 -8인 것은 조금 이상합니다.내가 에서 틀릴지도 모릅니다.C Programming하지만 그것은 옳은 일입니다 ;)

아래 코드를 사용하여 텍스트 필드가 비어 있더라도 키보드 삭제 키를 감지하는 데 도움이 됩니다.

목표 C:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }

스위프트:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }

사용해 보십시오.delegate

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

그리고 나서 확인합니다.range.length == 1그럴 때가 바로 그런 것 같습니다.backspace맞았습니다.

Niklas Alvaeus의 대답은 비슷한 문제를 해결하는 데 도움이 되었습니다.

특정 문자 집합에 대한 입력을 제한했지만 백스페이스를 무시했습니다.그래서 확인했습니다.range.length == 1손질하기 전에NSString사실이라면 끈만 돌려주고 다듬지는 않습니다.를 참조

 - (BOOL) textField:(UITextField *)textField 
          shouldChangeCharactersInRange:(NSRange)range 
          replacementString:(NSString *)string
 {
     NSCharacterSet *nonNumberSet = 
      [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] 
         invertedSet];

    if (range.length == 1) {
       return string;
    }
    else {
       return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
    }   
 }

예, textField가 비어 있는 경우 다음 방법을 사용하여 백스페이스를 탐지합니다.

UITextFieldDelegate를 추가해야 합니다.

textField.delegate = self(필수)

스위프트:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { 
    return true
}

목표 C:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
    return YES; 
}

제이콥의 답변에 문제가 있는 사람들을 위해 다음과 같이 텍스트 필드 하위 클래스를 구현했고 잘 작동합니다!

#import <UIKit/UIKit.h>

@class HTTextField;

@protocol HTBackspaceDelegate <NSObject>

@optional
- (void)textFieldDidBackspace:(HTTextField*)textField;
@end

@interface HTTextField : UITextField<UIKeyInput>

@property (nonatomic, assign) id<HTBackspaceDelegate> backspaceDelegate;

@end


#import "HTTextField.h"

@implementation HTTextField

- (void)deleteBackward {
    [super deleteBackward];
    if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidBackspace:)]){
        [self.backspaceDelegate textFieldDidBackspace:self];
    }
}

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
    BOOL shouldDelete = YES;

    if ([UITextField instancesRespondToSelector:_cmd]) {
        BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd];

        if (keyboardInputShouldDelete) {
            shouldDelete = keyboardInputShouldDelete(self, _cmd, textField);
        }
    }

    if (![textField.text length] && [[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
        [self deleteBackward];
    }

    return shouldDelete;
}

@end

를 탐지하는 가 빈 를 감지하는 입니다.UITextField예를 들어, 메일 앱에 '버블' 수신자가 있는 경우 다음에서 백스페이스를 누를 때UITextField마지막 '문제가 있는' 수신자를 선택합니다.

이것은 제이콥 카라발로의 대답과 유사한 방법으로 이루어질 수 있습니다.하지만 제이콥의 대답에 따르면, 만약UITextField까지 한 .UITextField이미 비어 있을 것이므로, 당신은 효과적으로 그것을 감지하고 있습니다.backspace텍스트 필드에 최대 한 글자까지 입력할 수 있습니다.

사실을 하고 싶다면 당만이발고싶다면하견신약▁actually싶다면▁if.backspace에서.UITextField로 .delegate 전화하기 super deleteBackward예:

#import "MyTextField.h"

//Text field that detects when backspace is hit with empty text
@implementation MyTextField

#pragma mark - UIKeyInput protocol
-(void)deleteBackward
{
  BOOL isTextFieldEmpty = (self.text.length == 0);
  if (isTextFieldEmpty) {
    if ([self.delegate 
         respondsToSelector:@selector(textFieldDidHitBackspaceWithEmptyText:)]) {

        [self.delegate textFieldDidHitBackspaceWithEmptyText:self];
        }
    }
    [super deleteBackward];
}
@end

이러한 텍스트 필드의 인터페이스는 다음과 같습니다.

@protocol MyTextFieldDelegate;

@interface MyTextField : UITextField
@property(nonatomic, weak) id<MyTextFieldDelegate> delegate;
@end

@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end

iOS 6에서 deleteBackward 메서드는 빈 필드를 포함하여 백스페이스를 누를 때 UI 텍스트 필드에서 호출됩니다.따라서 UITextField를 하위 분류하고 자체 deleteBackward 구현(슈퍼도 호출)을 제공할 수 있습니다.

저는 여전히 iOS 5를 지원하기 때문에 Andrew의 답변과 이것을 조합해야 합니다.

.h 파일에 UIKeyInput 대리자 추가

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

if ([textField isEqual:_txtFirstDigit]) {

}else if([textField isEqual:_txtSecondDigit]) {
    [_txtFirstDigit becomeFirstResponder];

}else if([textField isEqual:_txtThirdDigit]) {
    [_txtSecondDigit becomeFirstResponder];

}else if([textField isEqual:_txtFourthDigit]) {
    [_txtThirdDigit becomeFirstResponder];
}
return YES;
}   

개선된 서식

:) 하는 " backspace만 :) "Detect backspace"를 사용합니다UIKeyboardTypeNumberPad.

저도 오늘 밤 같은 질문을 받습니다. 그리고 그것을 알아내기 위한 코드는 다음과 같은 코드를 가지고 있습니다.

- (BOOL)textField:(UITextField *)textField 
        shouldChangeCharactersInRange:(NSRange)range 
        replacementString:(NSString *)string
{
    NSLog([NSString stringWithFormat:@"%d", [string length]]);
}

냐하면과 함께.UIKeyboardTypeNumberPad사용자는 숫자 또는 백스페이스만 입력할 수 있으므로 문자열 길이가 0인 경우 백스페이스 키여야 합니다.

위의 내용이 도움이 되길 바랍니다.

에 구성하거나 문자가 보다, 다음과 같습니다.shouldChangeCharactersInRange방법은 다음과 같습니다.

[self performSelector:@selector(manageSearchResultsDisplay) 
           withObject:nil 
           afterDelay:0];

이렇게 하면 현재 작업이 완료된 후 바로 메서드를 호출할 수 있습니다. 멋진 이것이 까지, 된 값은 에대멋점진은한, 완때까지될다것입는, ▁already▁will▁in▁be▁what다▁value입것,니▁that▁modified▁the는▁this▁is▁completes,것'라이▁about▁cool에 있을 것이라는 것입니다.UITextField이 시점에서 해당 길이를 확인하거나 내용을 기반으로 검증할 수 있습니다.

하위 분류 UI 텍스트 필드는 iOS 8.3에서 작동하지 않았습니다. deleteBackward는 호출되지 않았습니다.

여기 제가 사용한 솔루션이 있습니다. 모든 iOS 8 버전에서 작동하고 다른 iOS 버전에서도 작동해야 합니다.

for textField in textFields {
            textField.text = " "
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        if string == "" && textField.text == " "   {
            // Do stuff here
            return false
        }
        return true
}

저는 사용자가 백스페이스를 탭했을 때 텍스트 필드에 값이 있는지 여부를 알려주는 약간의 개선을 통해 유사한 솔루션을 구현했습니다.이것은 백스페이스를 눌렀을 때 텍스트 필드가 비어 있는 경우 다른 텍스트 필드에만 초점을 맞춰야 하는 경우에 유용합니다.

protocol MyTextFieldDelegate : UITextFieldDelegate {
    func textFieldDidDelete(textField: MyTextField, hasValue: Bool)
}

override func deleteBackward() {
    let currentText = self.text ?? ""
    super.deleteBackward()
    let hasValue = currentText.isEmpty ? false : true
    if let delegate = self.delegate as? MyTextFieldDelegate {
        delegate.textFieldDidDelete(textField: self, hasValue: hasValue)
    }
}

가장 일반적인 답변은 텍스트 필드가 비어 있는지 여부를 탐지하는 기능인 한 가지가 누락되었습니다.

있는지 수 ( 즉, TextField 위하클래의스이 이deleteBackwards() 메, 서, 를, deleteBackwards() 필트도드텍스재모가해이드있여다알수없의부두니후습를비과지정전는미어▁(backbackfield▁that▁text(▁field▁of)classdelete▁text▁(both,▁was즉▁whether▁don▁the,field▁delete(textField.text!는 빈 문자열입니다."")

삭제하기 전에 빈 곳이 없는지 확인하여 개선 사항을 알려드립니다.

UITextFieldDelegate를 확장하는 대리자 프로토콜 만들기

protocol MyTextFieldDelegate: UITextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
}

하위 클래스 UI 텍스트 필드

class MyTextField: UITextField {
    override func deleteBackward() {
        // see if text was empty
        let wasEmpty = text == nil || text! == ""

        // then perform normal behavior
        super.deleteBackward()

        // now, notify delegate (if existent)
        (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
    }
}

새 대리자 프로토콜 구현

extension MyViewController: MyTextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        if wasEmpty {
            // do what you want here...
        }
    }
}

Swift 5.1용 한 자리 숫자의 텍스트 필드에 대한 포괄적인 처리기:

  • textFields의 아웃렛 컬렉션이 있다고 가정합니다(연결된 딜러도 있음).

1단계

protocol MyTextFieldDelegate: class {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) 
}

final class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        let wasEmpty = text == nil || text == ""

        // then perform normal behavior
        super.deleteBackward()

        // now, notify delegate (if existent)
        (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
    }
}

2단계

final class ViewController: UIViewController {

    @IBOutlet private var textFields: [MyTextField]!

    override func viewDidLoad() {
        super.viewDidLoad()
        textFields.forEach {
            $0.delegate = self
            $0.myDelegate = self
        }
    }
}

3단계

extension ViewController: UITextFieldDelegate, MyTextFieldDelegate {
    func textFieldHasChanged(with text: String, _ tag: Int, for textField: UITextField) {
        textField.text = text

        if let someTextField = (textFields.filter { $0.tag == tag }).first {
            someTextField.becomeFirstResponder()
        } else {
            view.endEditing(true)
        }
    }

    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        // If the user was pressing backward and the value was empty, go to previous textField
        textFieldHasChanged(with: "", textField.tag - 1, for: textField)
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // Restrict to only digits
        let aSet = NSCharacterSet(charactersIn: "0123456789").inverted
        let compSepByCharInSet = string.components(separatedBy: aSet)
        let numberFiltered = compSepByCharInSet.joined(separator: "")

        guard string == numberFiltered, let text = textField.text else { return false }

        if text.count >= 1 && string.isEmpty {
            // If the user is deleting the value
            textFieldHasChanged(with: "", textField.tag - 1, for: textField)
        } else {
            textFieldHasChanged(with: string, textField.tag + 1, for: textField)
        }

        return false
    }
}

여기 @andrew 아이디어를 기반으로 한 솔루션이 있습니다.

예를 들어 viewDidLoad의 경우

        textField.delegate = self
        textField.addTarget(self, action: #selector(valueChanged(_:)), for: .editingDidBegin)

그리고 나서.

    @objc func valueChanged(_ textField: UITextField) {
        textField.text = "\u{200B}"
    }

    override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        textField.text = string
        if string == "" {
            //backpaspace pressed 
        }

모든 답변이 매우 도움이 되고 왜 모두가 의전 경로를 택하는지 모르겠습니다.콜백 기능을 사용하면 훨씬 적은 코드로 할 수 있습니다.

Swift 5.0 이상

  1. UITextField를 확장하는 사용자 지정 텍스트 필드 클래스를 만들고 deleteBackward 함수를 재정의합니다.

    클래스 사용자 지정텍스트 필드: UI 텍스트 필드 {}

     var backButtonPressedInEmptyTextField: (()->())?
    
     override func deleteBackward() {
         super.deleteBackward()
         if let text = self.text, text.count == 0{
             backButtonPressedInEmptyTextField?()
             print("Back space clicked when textfield is empty")
         }
     }
    

    }

  2. ViewController에 합니다.MyViewController래서에서.MyViewController그냥 따라하기만 하면 됩니다.

    클래스 MyView 컨트롤러:UIViewController{ @IBOutlet 약한 var 샘플텍스트 필드: 사용자 정의텍스트 필드!didSet{샘플TextField.back 버튼이 비어 있음TextField = backButtonPressed() } }

     func backButtonPressed(){
         //do whatever you want
     }
    

    }

클로저나 콜백 기능이 있는 것 같아요, 훨씬 깨끗합니다.

이와 같은 것:

- (BOOL)textField:(UITextField *)textField 
        shouldChangeCharactersInRange:(NSRange)range 
        replacementString:(NSString *)string       
{  
    if (![text hash] && ![textField.text length])  
        [self backspaceInEmptyTextField];  
}

물론 해시는 하나의 문자열에 대한 것입니다.

TextField Delegate 메서드 사용:

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

삭제 이벤트를 탐지하기 위해 위의 방법에 다음 코드를 추가합니다.

if(textField == YourTextField)
{
    if ([string length] == 0 && range.length > 0)
    {
        // Your Code after deletion of character
    }
}
+ (BOOL)detectBackspaceOnly:(NSString *)string
{
    for(int i=0 ; i<string.length ; i++){
        unichar caract = [string characterAtIndex:i];
        if(caract != ' ' && caract != '\n')
            return NO;
    }

    return YES;
}

텍스트 보기/필드의 텍스트를 확인하여 텍스트 보기/필드가 비어 있는지 확인하고 대체 텍스트도 shouldChangeTextIn 위임 메서드에서 비어 있는지 확인할 수 있습니다.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if (textView.text == "" && text == "") {
        print("Backspace on empty text field.")
    }
    return true
}

단순성을 유지하려면 여기서 확인해야 하는 유일한 조건입니다.

     if (range.length==1)

UITextViewDelegate:

- (BOOL)               textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
                replacementText:(NSString *)text
{
    if(text isEqualToString:@"");
    {
        NSLog(@"press backspace.");
    }
}

저한테는 잘 됩니다.

중국어 간체 핀인 및 중국어 필기 입력에 대한 업데이트:

- (BOOL)               textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
                replacementText:(NSString *)text
{
    if (range.length > 0 && [text isEqualToString:@""]) {
        NSLog(@"press Backspace.");
    }
    return YES;
}

문서에 따르면 다음과 같습니다.

가 " ▁the누▁the▁"deleteKey범위의 길이는 1이고 빈 문자열 개체가 해당 단일 문자를 대체합니다."

언급URL : https://stackoverflow.com/questions/1977934/detect-backspace-in-empty-uitextfield

반응형