ios - حدث تغيير نص UITextField




objective-c swift (12)

كيف يمكنني الكشف عن أي تغييرات نص في textField؟ يجب أن تعمل طريقة المفوض " shouldChangeCharactersInRange على شيء ، ولكنها لم shouldChangeCharactersInRange تمامًا. منذ أن ترجع "نعم" ، لا تتوفر النصوص textField لأساليب المراقبة الأخرى.

على سبيل المثال ، في رمز بلدي calculateAndUpdateTextFields EndUpdateTextFields لم تحصل على النص المحدث ، وقد كتب المستخدم.

هي أي طريقة للحصول على شيء مثل textChanged Java event handler.

- (BOOL)textField:(UITextField *)textField 
            shouldChangeCharactersInRange:(NSRange)range 
            replacementString:(NSString *)string 
{
    if (textField.tag == kTextFieldTagSubtotal 
        || textField.tag == kTextFieldTagSubtotalDecimal
        || textField.tag == kTextFieldTagShipping
        || textField.tag == kTextFieldTagShippingDecimal) 
    {
        [self calculateAndUpdateTextFields];

    }

    return YES;
}

جواب XenElement على الفور.

يمكن عمل ما سبق في أداة إنشاء الواجهة أيضًا بالنقر بزر الماوس الأيمن فوق UITextField وسحب حدث الإرسال "تغيير الملف" إلى وحدة الفئة الفرعية الخاصة بك.


سويفت 3 نسخة:

class SomeClass: UIViewController, UITextFieldDelegate { 

   @IBOutlet weak var aTextField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        aTextField.delegate = self
        aTextField.addTarget(self, action: #selector(SignUpVC.textFieldDidChange), for: UIControlEvents.editingChanged)        
    }

   func textFieldDidChange(_ textField: UITextField) {

       //TEXT FIELD CHANGED..SECRET STUFF

   }

}

لا تنسى تعيين المندوب.


كما هو مذكور هنا: حدث تغيير نص UITextField ، يبدو أنه اعتبارًا من iOS 6 (iOS 6.0 و 6.1 تم التحقق منه) ، لا يمكن اكتشاف التغييرات الكاملة في كائنات UITextField فقط من خلال ملاحظة UITextFieldTextDidChangeNotification .

يبدو أنه تم تتبع تلك التغييرات التي تم إجراؤها مباشرةً من خلال لوحة مفاتيح iOS المدمجة الآن. هذا يعني أنه إذا قمت بتغيير كائن UITextField فقط عن طريق استدعاء شيء مثل هذا: myUITextField.text = @"any_text" ، لن يتم إعلامك بأي تغييرات على الإطلاق.

لا أعلم ما إذا كان هذا خطأ أم لا. يبدو وكأنه خطأ منذ لم أجد أي تفسير معقول في الوثائق. هذا مذكور هنا أيضًا: حدث تغيير نص UITextField .

بلدي "الحل" لهذا هو في الواقع نشر إخطار بنفسي عن كل تغيير أقوم به إلى UITextField بي (إذا تم ذلك التغيير دون استخدام لوحة المفاتيح المدمج في نظام التشغيل iOS). شيء من هذا القبيل:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

NSNotification *myTextFieldUpdateNotification  = 
  [NSNotification notificationWithName:UITextFieldTextDidChangeNotification
                  object:myUITextField];

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

بهذه الطريقة ، ستكون واثقاً 100٪ من أنك ستتلقى نفس الإخطار عندما تقوم بتغيير خاصية UITextField لكائن UITextField ، إما عند تحديثه "يدويًا" في شفرتك أو من خلال لوحة مفاتيح iOS المدمجة.

من المهم أن تضع في اعتبارك أنه نظرًا لأن هذا ليس سلوكًا موثقًا ، فقد يؤدي هذا الأسلوب إلى تلقي إخطارات من أجل التغيير نفسه في كائن UITextField الخاص بك. اعتمادا على احتياجاتك (ما تفعله في الواقع عندما يتغير UITextField.text الخاص بك) قد يكون هذا إزعاجًا بالنسبة لك.

هناك طريقة مختلفة اختلافًا طفيفًا تتمثل في إرسال إشعار مخصص (هذا ، مع اسم مخصص بخلاف UITextFieldTextDidChangeNotification ) إذا كنت بحاجة بالفعل إلى معرفة ما إذا كان الإشعار الخاص بك هو "iOS-made" أم لا.

تصحيح:

لقد وجدت للتو نهجا مختلفا وأعتقد أنه يمكن أن يكون أفضل:

يتضمن ذلك ميزة مراقبة القيمة الرئيسية (KVO) في Objective-C ( http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA ).

بشكل أساسي ، تسجِّل نفسك كمراقب لأحد الممتلكات ، وإذا تغيرت هذه الخاصية ، فسيتم إعلامك بها. يشبه "المبدأ" تمامًا الطريقة التي يعمل بها NSNotificationCenter ، كونها الميزة الرئيسية التي يعمل بها هذا الأسلوب تلقائيًا أيضًا كما في نظام iOS 6 (دون الحاجة إلى إجراء تعديلات خاصة مثل الحاجة إلى نشر الإعلامات يدويًا).

بالنسبة إلى UITextField -scenario ، يعمل هذا بشكل جيد إذا أضفت هذا الرمز إلى ، على سبيل المثال ، UIViewController الذي يحتوي على حقل النص:

static void *myContext = &myContext;

- (void)viewDidLoad {
  [super viewDidLoad];

  //Observing changes to myUITextField.text:
  [myUITextField addObserver:self forKeyPath:@"text"
    options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld 
    context:myContext];

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
change:(NSDictionary *)change context:(void *)context {

  if(context == myContext) {
    //Here you get notified every time myUITextField's "text" property is updated
    NSLog(@"New value: %@ - Old value: %@",
      [change objectForKey:NSKeyValueChangeNewKey],
      [change objectForKey:NSKeyValueChangeOldKey]);
  }
  else 
    [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context];

}

الفضل في هذه الإجابة بخصوص إدارة "السياق": https://.com/a/12097161/2078512

ملاحظة: يبدو أنه أثناء قيامك بتحرير UITextField باستخدام لوحة مفاتيح iOS المدمجة ، لن يتم تحديث خاصية "text" الخاصة بحقل النص مع كل حرف جديد مكتوب / تمت إزالته. بدلاً من ذلك ، يتم تحديث كائن حقل النص "ككل" بعد استرجاع حالة المستجيب الأول لحقل النص.


ل Swift 3.0:

let textField = UITextField()

textField.addTarget(
    nil,
    action: #selector(MyClass.textChanged(_:)),
    for: UIControlEvents.editingChanged
)

باستخدام فئة مثل:

class MyClass {
    func textChanged(sender: Any!) {

    }
}

لقد حلت مشكلة تغيير سلوك shouldChangeChractersInRange. إذا رجعت ، فلن يتم تطبيق التغييرات من قِبل دائرة الرقابة الداخلية داخليًا ، بدلاً من ذلك لديك الفرصة لتغييرها يدويًا وتنفيذ أي إجراءات بعد إجراء التغييرات.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //Replace the string manually in the textbox
    textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
    //perform any logic here now that you are sure the textbox text has changed
    [self didChangeTextInTextField:textField];
    return NO; //this make iOS not to perform any action
}

مع إغلاق:

   class TextFieldWithClosure: UITextField {
    var targetAction: (() -> Void)? {
        didSet {
            self.addTarget(self, action: #selector(self.targetSelector), for: .editingChanged)
        }
    }

    func targetSelector() {
        self.targetAction?()
    }
    }

واستخدام

textField.targetAction? = {
 // will fire on text changed
 }

هنا في إصدار سريع لنفسه.

textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)

func textFieldDidChange(textField: UITextField) {

}

شكر


يجب عليك استخدام الإعلام لحل هذه المشكلة ، لأن الطريقة الأخرى سوف تستمع إلى مربع الإدخال وليس المدخلات الفعلية ، خاصة عند استخدام طريقة الإدخال الصينية. في viewDidload

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:)
                                                 name:@"UITextFieldTextDidChangeNotification"
                                               object:youTarget];

ثم

- (void)textFiledEditChanged:(NSNotification *)obj {
UITextField *textField = (UITextField *)obj.object;
NSString *toBestring = textField.text;
NSArray *currentar = [UITextInputMode activeInputModes];
UITextInputMode *currentMode = [currentar firstObject];
if ([currentMode.primaryLanguage isEqualToString:@"zh-Hans"]) {
    UITextRange *selectedRange = [textField markedTextRange];
    UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    if (!position) {
        if (toBestring.length > kMaxLength)
            textField.text =  toBestring;
} 

}

أخيرا ، قمت بتشغيل ، وسوف تفعل.


اختبار سويفت النسخة:

//Somewhere in your UIViewController, like viewDidLoad(){ ... }
self.textField.addTarget(
        self, 
        action: #selector(SearchViewController.textFieldDidChange(_:)),
        forControlEvents: UIControlEvents.EditingChanged
)

المعلمات الموضحة:

self.textField //-> A UITextField defined somewhere in your UIViewController
self //-> UIViewController
.textFieldDidChange(_:) //-> Can be named anyway you like, as long as it is defined in your UIViewController

ثم أضف الطريقة التي أنشأتها أعلاه في UIViewController :

//Gets called everytime the text changes in the textfield.
func textFieldDidChange(textField: UITextField){

    print("Text changed: " + textField.text!)

}

سويفت 3 نسخة

yourTextField.addTarget(self, action: #selector(YourControllerName.textChanges(_:)), for: UIControlEvents.editingChanged)

واحصل على التغييرات هنا

func textChanges(_ textField: UITextField) {
    let text = textField.text! // your desired text here
    // Now do whatever you want.
}

آمل أن يساعد.


سويفت 4

func addNotificationObservers() {

    NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChangeAction(_:)), name: .UITextFieldTextDidChange, object: nil)

}

@objc func textFieldDidChangeAction(_ notification: NSNotification) {

    let textField = notification.object as! UITextField
    print(textField.text!)

}

سويفت:

yourTextfield.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)

ثم قم بتطبيق وظيفة رد الاتصال:

@objc func textFieldDidChange(textField: UITextField){

print("Text changed")

}




uitextfielddelegate