使用self.delegate对UITextField进行子类化会导致应用冻结,CPU峰值达到100%

时间:2014-10-21 13:43:43

标签: ios objective-c delegates subclass uitextfielddelegate

我有一个UITextField的子类,它设置了self.delegate = self。子类用于防止将特殊字符输入UITextField。起初它工作正常,但在按下几个键之后,CPU峰值达到100%并冻结应用程序。 Xcode中没有崩溃日志,因为应用程序实际上从未崩溃,只是在我停止之前一直保持冻结状态。经过一些研究,我确定问题是将delegate设置为self - 显然我应该为delegate单独UITextField?我在网上搜索过,但找不到有关如何做到这一点的任何有用信息。

我的AcceptedCharacters子类:

AcceptedCharacters.h

#import <UIKit/UIKit.h>

@interface AcceptedCharacters : UITextField <UITextFieldDelegate>

@end

AcceptedCharacters.m

#import "AcceptedCharacters.h"
#define ACCEPTABLE_CHARACTERS @" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."

@implementation AcceptedCharacters

- (void)awakeFromNib
{
    [super awakeFromNib];

    if (self) {
        self.delegate = self;
    }
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //NSLog(@"AcceptedCharacters");
    // Restrict special characters
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
    NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];

    return [string isEqualToString:filtered];
}

@end

Xcode CPU Report

我在堆栈溢出时发现的类似问题:

Application freezes after editing custom UITextField

UITextField delegate jumping to 100% CPU usage and crashing upon using keyboard shortcut

Why does UITextField lock up when setting itself to delegate

我已阅读过这些解决方案,但对于初学者而言,它们相当模糊。我非常感谢有人修改我的代码,甚至指向我的教程或文档的方向?提前谢谢。

编辑:

我已在我的ViewControllers之一上测试了此代码,并且在符合UITextFieldDelegate协议且文本字段delegates设置为self时效果正常(请参阅下面的片段)。

在我的viewDidLoad方法中:

self.forenameField.delegate = self;
self.surnameField.delegate = self;
self.addLine1Field.delegate = self;
self.addLine2Field.delegate = self;
self.addLine3Field.delegate = self;
self.addLine4Field.delegate = self;
self.addLine5Field.delegate = self;
self.postcodeField.delegate = self;
self.telLandField.delegate = self;
self.telMobField.delegate = self;
self.emailField.delegate = self;
self.dobField.delegate = self;
self.niNumField.delegate = self;

我宁愿创建几个UITextField的子类,并在特定的文本字段上调用它们,而不是像下面那样有一个混乱的方法。

#define ACCEPTABLE_CHARACTERS @" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."
#define NUMBERS_ONLY @"1234567890"
#define CHARACTER_LIMIT 11
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    // Restrict special characters
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
    NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];

    // Convert postcode field characters to uppercase
    if (textField == self.postcodeField) {
        [textField setText:[textField.text stringByReplacingCharactersInRange:range withString:[string uppercaseString]]];
        return NO;
    }

    // Set max character limit on tel fields
    if (textField == self.telMobField || textField == self.telLandField) {
        NSUInteger newLength = [textField.text length] + [string length] - range.length;
        NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS_ONLY] invertedSet];
        NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
        return (([string isEqualToString:filtered])&&(newLength <= CHARACTER_LIMIT));
    }
    //return YES;
    return [string isEqualToString:filtered];
}

1 个答案:

答案 0 :(得分:1)

请改为尝试:

@interface MyTextField : UITextField
- (BOOL)stringIsAcceptable:(NSString *)string inRange:(NSRange)range;
@end
@implementation MyTextField
- (BOOL)stringIsAcceptable:(NSString *)string inRange:(NSRange)range {
  NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:ACCEPTABLE_CHARACTERS] invertedSet];
  NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];

  return [string isEqualToString:filtered];
}
@end

@interface PostalCodeTextField : MyTextField
@end
@implementation PostalCodeTextField
- (BOOL)stringIsAcceptable:(NSString *)string inRange:(NSRange)range {
  [self setText:[self.text stringByReplacingCharactersInRange:range withString:[string uppercaseString]]];
  return NO;
}
@end

.. more subclasses

然后将视图控制器指定为委托并在视图控制器中:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  if ([textField isKindOfClass:[MyTextField class]]) {
    return [(MyTextField *)textField stringIsAcceptable:string inRange:range];
  }
  return YES;
}