ตรวจจับ backspace ใน UITextField ว่างเปล่า


126

มีวิธีใดบ้างในการตรวจจับเมื่อกดปุ่มBackspace/ Deleteบนแป้นพิมพ์ iPhone บนUITextFieldที่ว่างเปล่า ฉันต้องการทราบว่าเมื่อใดที่Backspaceถูกกดเมื่อUITextFieldว่างเท่านั้น


จากคำแนะนำจาก @Alex Reynolds ในความคิดเห็นฉันได้เพิ่มรหัสต่อไปนี้ในขณะที่สร้างช่องข้อความของฉัน:

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

ได้รับการแจ้งเตือนนี้ ( handleTextFieldChangedเรียกใช้ฟังก์ชัน) แต่ยังไม่ได้เมื่อฉันกดBackspaceแป้นในช่องว่าง ความคิดใด ๆ ?


คำถามนี้ดูเหมือนจะมีความสับสน ฉันต้องการรับการแจ้งเตือนเมื่อBackspaceกดปุ่ม แค่นั้นแหละ. แต่โซลูชันจะต้องใช้งานได้เมื่อค่าUITextFieldว่างอยู่แล้ว


ฉันคิดว่าคุณอาจหมายถึง "เฉพาะในกรณีที่ UITextField ว่างเปล่า" แทนที่จะเป็น "เฉพาะในกรณีที่แป้นพิมพ์ว่างเปล่า" ... ?
Steve Harrison

@ สตีฟแฮร์ริสัน: ขอบคุณ อัปเดตว่า.
marcc

ฉันกำลังพยายามทำบางอย่างที่คล้ายกันคุณได้วิธีแก้ปัญหาอะไรบ้าง? สิ่งที่ฉันทำคือช่องข้อความในมุมมองแบบเลื่อนเมื่อฉันพิมพ์ข้อความคำแนะนำจะปรากฏขึ้นและเมื่อฉันคลิกที่หนึ่งวัตถุป้ายกำกับจะถูกวางไว้ทางด้านซ้ายของช่องข้อความ ขอบคุณล่วงหน้า: D
Dough

2011/11 วิธีการแก้ปัญหาสำหรับ UITextField ที่ว่างเปล่าโดยใช้กลอุบายรันไทม์: bjhomer.blogspot.com/2011/11/...
Jano

4
นานอย่างน่าขันสำหรับบางสิ่งที่ไม่สำคัญ เรื่องนี้น่าจะทำได้ไม่ยาก
Adam Waite

คำตอบ:


36

นี่อาจจะใช้เวลานาน แต่ก็ใช้ได้ผล \u200Bลองตั้งค่าข้อความฟิลด์ข้อความที่จะมีความกว้างศูนย์อักขระช่องว่าง เมื่อกด Backspace บนช่องข้อความที่ว่างเปล่าจะเป็นการลบพื้นที่ของคุณ จากนั้นคุณสามารถใส่ช่องว่างเข้าไปใหม่ได้

อาจใช้ไม่ได้หากผู้ใช้สามารถย้ายคาเร็ตไปทางซ้ายของช่องว่างได้


3
@ แอนดรูนี่คือแนวทางที่ฉันตัดสินใจทำ ใช้รหัสเล็กน้อย แต่ได้ผลอย่างแน่นอน ขอบคุณสำหรับความช่วยเหลือแทนที่จะพยายามบอกว่าฉันทำอะไรผิด
marcc

2
เทคนิคนี้อาจจะทำงานบน iPhone> 3.1.3 แต่ก็ hacky และอาจทำลายในรุ่นอนาคต ฯลฯ ผมคิดว่าผมพบว่าการทำความสะอาด, การแก้ปัญหาที่มีความเสถียรมากขึ้นสำหรับวิธีการตรวจสอบคีย์แป้นพิมพ์กดลบบน iPhone
ma11hew28

6
ฉันยืนยันได้ว่าไม่ตรวจพบการลบหากผู้ใช้สามารถเลื่อนเคอร์เซอร์ไปทางซ้ายของช่องว่างได้ หากคุณสามารถคิดออกวิธีการแก้ไขนั้นแล้วคุณควรซับคลาสUITextFieldและดำเนินcanPerformAction:withSender:การreturn NOสำหรับการselect:และการกระทำเมื่อข้อความเท่ากับสตริงselectAll: @"\u200B"
ma11hew28

2
ปัญหาคือใช้ไม่ได้กับฟิลด์ทดสอบที่ปลอดภัย มีความคิดว่าจะจัดการอย่างไร?
Kyle Clegg

7
ขออภัยความคิดนี้ไม่ดี เป็นการแฮ็กที่เหลือเชื่อและไม่ควรเป็นคำตอบที่ยอมรับด้วยการโหวต 30 ครั้งขึ้นไป ฉันจะคลาสย่อย UITextField แทนเช่นเดียวกับที่ผู้แสดงความคิดเห็นอื่น ๆ ได้กล่าวถึง
Brian Sachetta

155

Swift 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")
    }

}

Objective-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 myDelegateของคุณเป็น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");
}

9
นี่คือทางออกที่ดีที่สุด คำตอบที่ยอมรับคือแฮ็ค Objective C ขึ้นอยู่กับการแบ่งประเภทย่อยและโซลูชันนี้ใช้อย่างเหมาะสมในการแก้ปัญหา
TJ

จะเกิดอะไรขึ้นกับวิธีการมอบหมายที่มีอยู่ของฉันในViewController ชั้นเรียนถ้าฉันตั้งตัวแทนของช่องข้อความเป็นคลาสย่อยUITextFieldแทนที่จะเป็นUIViewController
rohan-patel

4
เห็นได้ชัดว่าสิ่งนี้ใช้ไม่ได้ใน ios8 ในขณะนี้เนื่องจากสิ่งที่ดูเหมือนบั๊กของ Apple: devforums.apple.com/message/1045312#1045312
chug2k

1
ฉันใช้วิธีแก้ปัญหาสำหรับข้อผิดพลาด ios8 ตามคำตอบของฉันและมันได้ผล อาจเป็นประโยชน์สำหรับผู้ที่กำลังค้นหาวิธีแก้ปัญหา
furkan3ayraktar

1
deleteBackward()จะไม่ถูกเรียกถ้าคุณreturn falseเข้าtextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
igrrik

41

อัพเดท: ดูคำตอบ JacobCaraballo ของ-[UITextField deleteBackward]ตัวอย่างที่แทนที่

ตรวจสอบUITextInputโดยเฉพาะUIKeyInputมีdeleteBackwardวิธีการมอบหมายที่จะถูกเรียกเสมอเมื่อกดปุ่มลบ หากคุณกำลังทำอะไรง่ายๆคุณอาจพิจารณาแค่คลาสย่อยUILabelและทำให้เป็นไปตามUIKeyInputโปรโตคอลดังที่ทำโดยSimpleTextInputและตัวอย่าง UIKeyInput ของ iPhoneนี้ หมายเหตุ: UITextInputและญาติ (รวมถึงUIKeyInput) พร้อมใช้งานใน iOS 3.2 และใหม่กว่าเท่านั้น


2
นี่คือคำตอบที่ใช่ ไม่แฮ็คและง่ายมากด้วย UITextField subclass อย่างรวดเร็ว
แซม

เพียงแค่เห็นคำตอบของเจคอบด้านล่าง มันให้ตัวอย่างโดยละเอียดเกี่ยวกับเรื่องนี้
แซม

เป็นที่น่าสังเกตว่าคำตอบนี้ใช้ไม่ได้ใน iOS 5 หากช่องข้อความว่างเปล่าการกด backspace จะไม่เรียกใช้วิธีนี้
jfeldman

31

รหัสดังต่อไปนี้:

@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

สุดท้ายอย่าลืมเปลี่ยนคุณสมบัติ Custom Class ของช่องข้อความเป็น "MyTextField"


5
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ สะอาดและตอบคำถามได้จริง
Ryan Romanchuk

1
ตอบคำถามได้ ... ตราบใดที่คุณกำหนดเป้าหมายเป็น iOS 6.0+ ใน iOS 5 deleteBackward ไม่เคยถูกเรียกในคลาสย่อยของคุณ แต่น่าเสียดาย
BJ Homer

2
BJ Homer อุปกรณ์ 93% ใช้ iOS 6 ดังนั้นการไม่กำหนดเป้าหมาย iOS 5 โดยทั่วไปจึงไม่ใช่เรื่องใหญ่
โจนาธาน

2
ฉันดีใจที่เลื่อนลงมาเรื่อย ๆ พอเจอสิ่งนี้ 100% วิธีที่ถูกต้องในวันนี้ใน IOS 7
MusiGenesis

ฉันได้เห็นคำตอบอื่น ๆ มากมายสำหรับคำถามนี้ซึ่งเป็นเพียงวิธีแก้ปัญหาและแทบจะไม่มีคำตอบใด ๆ ที่เกี่ยวข้องกับสถานการณ์ที่กดปุ่ม Backspace ในช่องว่าง อย่างไรก็ตามนี่เป็นวิธีที่สมบูรณ์แบบและเป็นวิธีที่สะอาดจริงๆ
Christopher Hannah

19

การใช้งานอย่างรวดเร็ว:

import UIKit

protocol PinTexFieldDelegate : 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? PinTexFieldDelegate {
            pinDelegate.didPressBackspace(self)
        }
    }
}

ขอบคุณขอทราบวิธีนี้แนะนำโดย apple หรือเป็นการแฮ็ก ดูเหมือนว่าไม่มีเอกสารสำหรับฟิลด์ข้อความ
kalpesh jetani

ทำงานให้ฉันด้วย textView ขอบคุณสำหรับการแบ่งปัน;)
Edouard Barbier

ทำงานให้ฉันเมื่อช่องข้อความว่างเปล่าและมีการคลิกพื้นที่ด้านหลัง
รามก

17

ฉันได้ค้นพบวิธีอื่นที่ง่ายกว่า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บางทีฉันอาจจะไม่ถูกต้องในบางจุด แต่มันทำงานได้ถูกต้อง;)


1
กรรเชียงไม่ได้ตั้งค่า "\ b" แต่ถ้าคุณแก้ไขจุดบกพร่องอย่างรอบคอบคุณจะเห็น "\ 0" ดังนั้นฉันจึงได้ผลลัพธ์ 0 นั่นคือค่าสองค่าเท่ากันในวิธี strcmp const char * stoke = [ข้อความ cStringUsingEncoding: NSASCIIStringEncoding]; const char * backstroke = "\ 0"; // นี่เท่ากับ \ b -> "\ x08"; strcmp (กรรเชียง, สโต๊ค);
Yoon Lee

นอกจากนี้ตามคำจำกัดความของ strcmp (s1, s2) จะส่งกลับ 0 ถ้า s1 == s2,> 0 s1 มีค่ามากกว่า s2 ในทางศัพท์
Yoon Lee

ฉันไม่เข้าใจว่ามันจะทำงานได้อย่างไร? @YoonLee: คุณไม่ได้บอกว่าstrcmpผลตอบแทน-1, 0, or 1เหรอ? นั่นคือความเข้าใจของฉัน
chug2k

1
ใน textview คุณจะตรวจจับ backspace ได้เสมอแม้ว่าจะไม่มีข้อความก็ตาม UITextField นั้นแตกต่างกัน
LolaRun

2
นี่คือวิธีการไม่ได้UITextViewDelegate UITextFieldDelegate
pkamb

12

ลองใช้ไฟล์ delegate

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

จากนั้นตรวจสอบrange.length == 1ว่ากรณีที่เกิดขึ้นเมื่อbackspaceถูกตีหรือไม่


8
เรียกเฉพาะเมื่อฟิลด์ไม่ว่างเปล่าเท่านั้น สังเกตคำถามเดิม :)
Eric Goldberg

ใช้ UITextView สำหรับสิ่งนี้
Oleg

11

โปรดใช้รหัสด้านล่างซึ่งจะช่วยให้คุณตรวจจับแป้นลบแป้นพิมพ์แม้ว่าช่องข้อความของคุณจะว่างเปล่าก็ตาม

วัตถุประสงค์ C:

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

รวดเร็ว:

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

Tx - แค่สิ่งที่ฉันต้องการ แต่มีเอกสารที่ไหน ??
Andy Weinstein

9

คำตอบของ Niklas Alvaeus ช่วยฉันแก้ปัญหาที่คล้ายกัน

ฉันกำลัง จำกัด การเข้าสู่ชุดอักขระเฉพาะ แต่มันไม่สนใจ backspaces ดังนั้นฉันจึงตรวจสอบ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);
    }   
 }

วิธีนี้คาดว่าบูลีนไม่ใช่สตริงเป็นค่าส่งคืน
Pascalius

4

สำหรับผู้ที่มีปัญหาเกี่ยวกับคำตอบของ Jacobฉันใช้คลาสย่อยของฟิลด์ข้อความดังต่อไปนี้และใช้งานได้ดี!

#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

คุณสามารถเขียนโค้ดเพื่อความรวดเร็ว ฉันได้รับข้อผิดพลาดบางอย่าง "การยืนยันซ้ำซ้อนกับโปรโตโก uikeyinput"
Raj Aggrawal

4

ใช่ใช้วิธีการด้านล่างเพื่อตรวจจับ backspace เมื่อ textField ว่างเปล่า

ต้องเพิ่มUITextFieldDelegate

yourTextField.delegate = self (ต้องมี)

สวิฟท์:

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

วัตถุประสงค์ C:

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

5
นี่ไม่ได้เรียกร้องให้ฉันด้วยซ้ำ วิธีการมอบหมายอื่น ๆ ทั้งหมดจะถูกเรียกว่าและเมื่อมีเหตุการณ์เกิดขึ้น
Hemang

ขอบคุณเพื่อน .. คุณตอกมัน :)
.

@ McDonal_11 ฉันคิดว่าคุณลืมตั้ง textfield.delegate = ตัวเองของช่องข้อความ
Himanshu padia

ฉันได้ตั้งค่า. วิธีการมอบหมายอื่น ๆ ของ UITextField ทำงานได้ดี อันนี้คนเดียวไม่ทำงาน คิดถึงอะไร ??
McDonal_11

3

การใช้งานที่ดีที่สุดที่ฉันได้พบในการตรวจสอบย้อนกลับคือการตรวจสอบเมื่อผู้ใช้กด Backspace UITextFieldในที่ว่างเปล่า ตัวอย่างเช่นหากคุณมีผู้รับ "bubbled" ในแอปอีเมลเมื่อคุณกด backspace ในไฟล์UITextFieldจะเลือกผู้รับ "bubbled" คนสุดท้าย

สามารถทำได้ในลักษณะเดียวกับคำตอบของ Jacob Caraballo แต่ในคำตอบของเจคอบหากUITextFieldมีอักขระหนึ่งตัวที่เหลืออยู่เมื่อคุณกด backspace เมื่อถึงเวลาที่ได้รับข้อความผู้รับมอบสิทธิ์สิ่งนั้นUITextFieldจะว่างเปล่าอยู่แล้วดังนั้นคุณจึงตรวจจับได้อย่างมีประสิทธิภาพbackspaceบนฟิลด์ข้อความที่มีอักขระไม่เกินหนึ่งตัว

ที่จริงถ้าคุณต้องการที่จะตรวจสอบ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

2
ในการสั่งซื้อสำหรับการทำงานใน iOS8 (ที่มีข้อผิดพลาดที่ก่อให้เกิดวิธีการผู้รับมอบสิทธิ์นี้ไม่เคยที่จะเรียก) โปรดดูคำตอบนี้: stackoverflow.com/a/25862878/893101 รายละเอียดเพิ่มเติมเกี่ยวกับข้อผิดพลาดios8
pIkEL

2

ใน iOS 6 เมธอด deleteBackward ถูกเรียกใช้บน UITextField เมื่อกด backspace รวมถึงเมื่อฟิลด์ว่าง ดังนั้นคุณสามารถ subclass UITextField และจัดเตรียมการใช้งาน deleteBackward ของคุณเอง (เรียกใช้ super's ด้วย)

ฉันยังคงรองรับ iOS 5 อยู่ดังนั้นฉันต้องการคำตอบของ Andrew และสิ่งนี้รวมกัน


1

:) สำหรับชื่อเรื่อง "Detect backspace" ที่ฉันใช้ UIKeyboardTypeNumberPadที่ผมใช้

ฉันยังพบคำถามเดียวกันในคืนนี้และต่อไปนี้คือรหัสของฉันเพื่อค้นหา:

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

เพราะด้วย UIKeyboardTypeNumberPadผู้ใช้สามารถป้อน Number หรือ backspace เท่านั้นดังนั้นเมื่อความยาวของสตริงเป็น 0 จึงต้องเป็นคีย์ backspace

หวังว่าข้างต้นจะช่วยได้บ้าง


เหมือนกับคีย์บอร์ดทุกประเภท
ma11hew28

ฉันจะเชื่อมต่อวิธีนี้กับช่องข้อความของฉันได้อย่างไร
user230910

1

แทนที่จะพยายามสร้างสิ่งที่จะอยู่ในช่องข้อความล่วงหน้าหรือคิดว่าอักขระพิเศษใดที่ถูกป้อนในshouldChangeCharactersInRangeวิธีการฉันขอแนะนำให้ทำสิ่งต่อไปนี้:

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

สิ่งนี้ช่วยให้คุณสามารถเรียกใช้เมธอดได้โดยตรงหลังจากการดำเนินการปัจจุบันเสร็จสิ้น สิ่งที่น่าสนใจคือเมื่อเสร็จสิ้นค่าที่แก้ไขจะอยู่ในไฟล์UITextField. ณ จุดนั้นคุณสามารถตรวจสอบความยาวและ / หรือตรวจสอบความถูกต้องตามสิ่งที่มี


1

UITextField Subclassing ใช้งานไม่ได้สำหรับฉันบน 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
}

1

ในไฟล์. 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;
}   

ปรับปรุงการจัดรูปแบบ


1

ฉันได้ใช้โซลูชันที่คล้ายกันนี้โดยมีการปรับปรุงเล็กน้อยซึ่งจะบอกฉันว่าหากฟิลด์ข้อความมีค่าใด ๆ ในขณะที่ผู้ใช้แตะแบ็กสเปซ สิ่งนี้มีประโยชน์สำหรับกรณีของฉันเมื่อฉันควรโฟกัสที่ช่องข้อความอื่นหากช่องข้อความว่างเปล่าเมื่อกด backspace

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)
    }
}

1

คำตอบแบบป็อปลาร์ส่วนใหญ่ขาดหายไปอย่างหนึ่งนั่นคือความสามารถในการตรวจจับว่าช่องข้อความว่างเปล่าหรือไม่

นั่นคือเมื่อคุณแทนที่เมธอด deleteBackwards () ของคลาสย่อย TextField คุณจะยังไม่รู้ว่าฟิลด์ข้อความนั้นว่างเปล่าอยู่หรือไม่ (ทั้งก่อนและหลัง deleteBackwards () textField.text!เป็นสตริงว่าง:"" )

นี่คือการปรับปรุงของฉันด้วยการตรวจสอบความว่างเปล่าก่อนที่จะลบ

1. สร้างโปรโตคอลผู้รับมอบสิทธิ์ที่ขยาย UITextFieldDelegate

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

2. คลาสย่อย UITextField

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)
    }
}

3. ใช้โปรโตคอลตัวแทนใหม่ของคุณ

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

1

ตัวจัดการที่ครอบคลุมสำหรับช่องข้อความที่มีตัวเลขหลักเดียวสำหรับ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
    }
}

0

นี่คือวิธีแก้ปัญหาของฉันตามแนวคิด @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 
        }

0

คุณสามารถตรวจสอบข้อความของมุมมองข้อความ / ฟิลด์เพื่อดูว่าว่างเปล่าและตรวจสอบให้แน่ใจว่าข้อความแทนที่ว่างเปล่าในวิธีการมอบหมาย shouldChangeTextIn

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

-2

สิ่งนี้:

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

แน่นอนว่าแฮชมีไว้สำหรับสตริงอักขระหนึ่งตัว


-2

ใช้วิธี 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
    }
}


-3
+ (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;
}

2
อาจจะมีคำอธิบายเล็กน้อยว่าจะวางสิ่งนี้ไว้ที่ไหน?
Alex Cio

-4

ใน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;
}

ตามเอกสารระบุว่า:

"ถ้าผู้ใช้กดปุ่มdeleteKeyความยาวของช่วงคือ 1 และอ็อบเจ็กต์สตริงว่างจะแทนที่อักขระเดี่ยวนั้น"


1
คำถามนี้เป็นคำถามเกี่ยวกับการไม่ได้UITextField UITextView
ma11hew28
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.