• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

UITextView/UITextField 设置字数限制,字符截断问题解决

武飞扬头像
猫南北学ios
帮助2

UITextView字数限制

  • 添加代理,在代理方法里面限制字数,可以在shouldChangeTextInRange方法里面限制,或者在textViewDidChange方法里面限制
- (void)viewDidLoad {
    [super viewDidLoad];
    // 添加并设置代理
    UITextView *textView = [[UITextView alloc] init];
    textView.frame = CGRectMake(0, 100, 390, 200);
    textView.delegate = self;
    [self.view addSubview:textView];
}

/// 方法一
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if (textView.text.length - range.length   text.length > 10) {
        NSLog(@"超出字数限制");
        return NO;
    }
    return YES;
}

/// 方法二
 - (void)textViewDidChange:(UITextView *)textView {
    // 限制字数
    if (textView.text.length > 10) {
        textView.text = [textView.text substringToIndex:10];
    }
}
学新通

UITextField字数限制

可以通过代理、Target监听和通知对UITextField字数进行限制

  • 通过代理限制字数
// 添加代理
textField.delegate = self;

// 代理方法
 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField.text.length - range.length   string.length > 20){
        return NO;
    }
    return YES;
}
  • 通过Target监听限制字数
// 添加监听
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
// 监听方法
 - (void)textFieldDidChange:(UITextField *)textField {
    if (textField.text.length > 20) {
        textField.text = [textField.text substringToIndex:20];
    }
}
  • 通过通知限制字数
    // NSNotificationCenter
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:) name:UITextFieldTextDidChangeNotification object:textField];

 - (void)textFiledEditChanged:(NSNotification *)notification {
   UITextField *textField = notification.object;
    // 限制字数
    if (textField.text.length > 10) {
        textField.text = [textField.text substringToIndex:10];
    }
}

高亮状态不做字数限制

  • 在限制方法里面添加对高亮状态的识别,高亮状态时,不做字符长度限制,通用UITextView/UITextField
    // 高亮状态
    if ([textView positionFromPosition:[textView markedTextRange].start offset:0]) {
        return;
    }

字符截断问题

  • ❓通常一个emoji表情😓占用2个字符(部分占用3-4个),所以在使用字符阶段函数substringToIndex的时候,一个emoji表情会被截断,出现无法识别字符的情况,变成一个奇怪的字符
  • 🔧解决方案:使用安全字符截断,附上h文件和m文件,可以创建一个NSString的Cut分类使用,或者复制想要的函数,根据需要选择emojiSubstringToIndex函数或者specialEmojiSubstringToIndex函数,区别在注释里面
//
//  NSString Cut.h
//
//  Created by 猫南北学iOS on 2023/1/16.
//
//  字符截取分类
//  对英文占用字符数改为单个字母占用0.5个字符
//
//  字符长度规则:
//  1、中文占有1个字符
//  2、英文占用0.5个字符(⚠️区别于一般的字符长度计算)
//  3、emoji占用2个字符(部分emoji 3-4个字符)

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSString (Cut)

/// 根据序号字符截取
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// 修复emoji表情字符截断问题
- (NSString *)specialEmojiSubstringToIndex:(NSInteger)index;

/// 根据序号字符截取
/// 规则:中英文字符都视为1个字符,emoji占用2个字符
/// 修复emoji表情字符截断问题
- (NSString *)emojiSubstringToIndex:(NSInteger)index;

/// 获取剩余可输入字数
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// - Parameter length: 限制字数长度
- (NSString *)inputLengthWithLimitLength:(NSInteger)length;

/// 获取字符长度
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// 返回整数,自动向上取整
- (NSInteger)characterLength;

/// 获取字符长度
/// 规则:中文占有2个字符,英文占用1个字符,emoji占用4个字符
- (NSInteger)doubleCharacterLength;

@end

NS_ASSUME_NONNULL_END
学新通
//
//  NSString Cut.m
//
//  Created by 猫南北学iOS on 2023/1/16.
//  字符截取分类
// 

#import "NSString Cut.h"

@implementation NSString (Cut)

/// 根据序号字符截取
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// 修复emoji表情字符截断问题
- (NSString *)specialEmojiSubstringToIndex:(NSInteger)index {
    // 字符为空
    if (!self || [self isEqualToString:@""]) {
        return nil;
    }
    // 期望长度
    NSInteger doubleIndex = index * 2;
    // 循环截取
    for (NSInteger i = 0; i < self.length; i  ) {
        // 截取
        NSString *result = [self emojiSubstringToIndex:self.length - i];
        // 截取的长度比较
        if (result.doubleCharacterLength <= doubleIndex) {
            return result;
        }
    }
    // 出错
    return nil;
}

/// 根据序号字符截取
/// 规则:中英文字符都视为1个字符,emoji占用2个字符
/// 修复emoji表情字符截断问题
- (NSString *)emojiSubstringToIndex:(NSInteger)index {
    NSString *result = self;
    if (result.length > index) {
        NSRange range = [result rangeOfComposedCharacterSequenceAtIndex:index];
        result = [result substringToIndex:(range.location)];
    }
    return result;
}

/// 获取剩余可输入字数
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// - Parameter length: 限制字数长度
- (NSString *)inputLengthWithLimitLength:(NSInteger)length {
    if (length < self.characterLength) {
        return @"0";
    }
    return [@(length - self.characterLength) stringValue];
}

/// 获取字符长度
/// 规则:中文占有1个字符,英文占用0.5个字符,emoji占用2个字符
/// 返回整数,自动向上取整
- (NSInteger)characterLength {
    return ceil(self.doubleCharacterLength / 2.0);
}

/// 获取字符长度
/// 规则:中文占有2个字符,英文占用1个字符,emoji占用4个字符
- (NSInteger)doubleCharacterLength {
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
    NSData *data = [self dataUsingEncoding:encoding];
    return [data length];
}

@end
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcaibi
系列文章
更多 icon
同类精品
更多 icon
继续加载