UITextView/UITextField检测并过滤Emoji表情符号

UITextView/UITextField检测并过滤Emoji表情符号

本人在开发过程中遇到过这种情况,服务器端不支持Emoji表情,因此要求客户端在上传用户输入时,不能包含Emoji表情。在客户端发送请求前,判断用户输入中是否含有表情,如果含有表情,则提示用户重新输入。这个过程关键是如何判断字符串中是否含有Emoji表情。要判断是否含有Emoji表情,必须先了解什么是Emoji。

百度百科中告诉我们“自苹果公司发布的iOS 5输入法中加入了emoji后,这种表情符号开始席卷全球,目前emoji已被大多数现代计算机系统所兼容的Unicode编码采纳,普遍应用于各种手机短信和社交网络中。[1] ”,Emoji表情最终会被编码成Unicode,因此,只要知道Emoji表情的Unicode编码的范围,就可以判断用户是否输入了Emoji表情。

经过多番查找资料和测试Demo,目前有以下两种方式比较合理:

  1. 当用户切换键盘为Emoji表情时,输入的表情不响应(即表情符号不显示到UITextView或UITextField)。这里可以通过UITextView或UITextField的回调和是否为emoji键盘:

    /*
    *第一种方法,简单粗暴
    */
    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
        // 不让输入表情
        if ([textView isFirstResponder]) {
            if ([[[textView textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textView textInputMode] primaryLanguage]) {
                NSLog(@"输入的是表情,返回NO");
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"不能输入表情" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
                [alertView show];
                return NO;
            }
        }
        return YES;
    }
    
  2. 为避免当用户通过中文键盘输入中文“哈哈”后出现可选文字中选中的Emoji笑脸,最后在- (void)textFieldDidEndEditing:(UITextField *)textField方法中统一通过检查最终字符串textField/textView.text的内容,通过Emoji筛unicode编码来判断是否存在Emoji表情,如果存在则提醒用户做修改。

    //在输入完成时,调用下面那个方法来判断输入的字符串是否含有表情
    - (void)textFieldDidEndEditing:(UITextField *)textField
    {
        if ([self stringContainsEmoji:textField.text]) {
            NSLog(@"含有表情");
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"输入内容含有表情,请重新输入" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
            [alertView show];
            textField.text = @"";
            [textField becomeFirstResponder];
        }else {
            NSLog(@"不含有表情");
        }
    
    }
    
    /*
     *第二种方法,利用Emoji表情最终会被编码成Unicode,因此,
     *只要知道Emoji表情的Unicode编码的范围,
     *就可以判断用户是否输入了Emoji表情。
     */
    - (BOOL)stringContainsEmoji:(NSString *)string
    {
        // 过滤所有表情。returnValue为NO表示不含有表情,YES表示含有表情
        __block BOOL returnValue = NO;
        [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    
            const unichar hs = [substring characterAtIndex:0];
            // surrogate pair
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (substring.length > 1) {
                    const unichar ls = [substring characterAtIndex:1];
                    const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        returnValue = YES;
                    }
                }
            } else if (substring.length > 1) {
                const unichar ls = [substring characterAtIndex:1];
                if (ls == 0x20e3) {
                    returnValue = YES;
                }
            } else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff) {
                    returnValue = YES;
                } else if (0x2B05 <= hs && hs <= 0x2b07) {
                    returnValue = YES;
                } else if (0x2934 <= hs && hs <= 0x2935) {
                    returnValue = YES;
                } else if (0x3297 <= hs && hs <= 0x3299) {
                    returnValue = YES;
                } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
                    returnValue = YES;
                }
            }
        }];
        return returnValue;
    }
    

ps:Demo已放在云盘里,链接: http://pan.baidu.com/s/1boguLgN 密码: keet

相关推荐:

如何在Python中实现基于用户协同过滤的简单推荐系统?

直接用scipy.spatial.distance.cosine易出错,因其默认对齐全部维度(含大量0)、不处理NaN、未中心化,导致稀疏数据下相似度失真;应先构建用户-物品矩阵并保留NaN,再基于共同评分项子集计算余弦相似度。 为什么直接用scipy.spatial.distance.cosine...

如何使用Python中的Isolation Forest算法实现生产环境的异常检测?

IsolationForest在生产环境不适合直接用于高吞吐、低延迟的实时流式场景,因其为无监督批处理算法,需完整训练集且无法在线更新模型,实际应采用周期性离线打分或结合轻量代理模型实现近实时响应。 IsolationForest在生产环境是否适合实时异常检测? 不适合直接用于高吞吐、低延迟的实时流...

Python中如何处理缺失值比例过高的特征列_设置阈值利用dropna自动过滤

当某列缺失值占比超过阈值(如70%)时应直接删除该列,因其建模价值低且插补易引入噪声;需用df.isnull().mean()计算各列缺失率,再布尔索引筛选并drop。 缺失值比例超过阈值就该直接删列,别犹豫 当某列缺失值占比超过70%(或你设定的业务阈值),它基本丧失了建模价值,强行插补反而引入噪...

如何在Python Flask中实现敏感词过滤_构建自定义中间件

Flask中不能直接在路由里做敏感词过滤,因重复代码多、易漏检、难统一响应格式,且无法覆盖所有入口;应使用WSGI中间件或before_request钩子在请求进入视图前拦截,中间件更底层可靠,职责仅为阻断而非清洗。 Flask中为什么不能直接在路由里做敏感词过滤 因为重复代码多、易漏检、难统一响应...

如何判断Python对象是否为可调用对象_使用callable函数检测

callable()检查对象是否实现__call__或属可调用类型,返回True仅表示语法上可加括号,不保证调用成功;类本身可调用,其实例需定义__call__才可调用,lambda、函数、内置函数等均返回True,但参数错误或运行时异常仍会导致调用失败。 callable函数的基本行为和常见误判 ...

Python中如何检测异步循环的卡顿情况_使用aiomonitor实时监控事件循环

aiomonitor能发现事件循环卡顿是因为它定期采样事件循环时间与任务栈快照,识别出“某任务运行超阈值(默认1s)”的异常状态,不依赖代码埋点,而是从运行时底层观测;普通日志仅记录主动写入的点,无法捕获静默发生的调度停滞。 为什么aiomonitor能发现事件循环卡顿,而普通日志不行 因为卡顿本质...