有的时候项目的对登录、注册等文本框的要求蛮高,超过字数不能再输入,这对英文或者数字的内容很好控制,但是中文的情况下就会出现很多问题,比如(假定限制文本框只能输入4个汉字,也就是8个英文+数字):
- 拼音模式下正在按着(比如:清者自清)的拼音,就会出现:**qing zhe **就不能再输入等情况;
- 又或者复制了一串十多个汉字(比如:台湾媒体一路给我很多很好的评价)的字符粘贴到文本框(理想情况:只保留‘台湾媒体’)时候是完完整整的并没有裁剪体后面的字符
下面的代码就能很好解决上述问题(只限制中文,英文,数字,阴文和淋语没有测试过):
- Swift版本(此段写于2016/12/19 适用于 Swift 3.0) :
代码中的 @IBInspectable 后面会说
import UIKit
class iTextField: UITextField {
@IBInspectable var maxLength : NSInteger = 0
//MARK:重写
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
p_setUpTextField()
}
override init(frame: CGRect) {
super.init(frame: frame)
p_setUpTextField()
}
//MARK:私有方法
private func p_setUpTextField(){
addTarget(self, action: #selector(p_textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
}
@objc private func p_textFieldDidChange(textField : UITextField) {
if markedTextRange?.start == nil {
let enc = CFStringConvertEncodingToNSStringEncoding(UInt32(CFStringEncodings.GB_18030_2000.rawValue))
let data = text?.data(using: String.Encoding(rawValue: enc))
let dataLength = (data?.count)! as Int
print(dataLength)
if dataLength > maxLength {
let subData = data?.subdata(in: 0 ..< maxLength)
var limitStr = String.init(data: subData!, encoding: String.Encoding(rawValue: enc))
if limitStr == nil {
limitStr = String.init(data: (data?.subdata(in: 0 ..< maxLength-1))!, encoding: String.Encoding(rawValue: enc))
}
setValue(limitStr, forKey: "text")
}
}
}
}
OC版本:
.h 文件中声明:
@property (nonatomic, assign) IBInspectable NSInteger maxLength;
.m文件:
#import "iTextField.h"
@implementation iTextField
#pragma mark - 重写方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self p_setTextField];
}
return self;
}
- (instancetype)init{
if (self = [super init]) {
[self p_setTextField];
}
return self;
}
#pragma mark - 私有方法
- (void)p_setTextField {
[self addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (void)textFieldDidChange:(UITextField *)textField
{
if (![self markedTextRange].start) {
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSData *toBeStringData = [self.text dataUsingEncoding:encoding];
NSInteger dataLength = [toBeStringData length];
if (dataLength > self.maxLength) {
NSString *limitString = [[NSString alloc] initWithData:[toBeStringData subdataWithRange:NSMakeRange(0, self.maxLength)] encoding:encoding];
if (!limitString)
limitString = [[NSString alloc] initWithData:[toBeStringData subdataWithRange:NSMakeRange(0, self.maxLength - 1)] encoding:encoding];
[self setValue:limitString forKey:@"text"];
}
}
}
@end
这样就可以完美解决开篇的两个尿黄精血的难题,没有上效果图,因为模拟器的效果很差(一闪一闪的),真机是没有问题的。
IBInspectable
项目中十有八九的UI元素都是自定义的,系统默认的属性在面板中都可以找到,拿UITextField为例(画圈部分并不陌生):
加上这个关键字的属性,面板中就会出现我们自己定义的属性一栏:
简单又实用,文件中就少了一份赋值代码。
另外:颜色、宽度、角度等属性也都能如此设置
另一个关键字:
IB_DESIGNABLE
,自定义的UI元素可以直接在XIB中预览~