微信相关

iOS 仿微信@功能

2020-06-06  本文已影响0人  daobao777

1.微信@功能实现思路

最近在封装IM聊天功能,微信@功能思考了许久想出了一个办法,用富文本的方式将@内容的空格特殊化,自定义两个NSAttributedStringKey,分别记录名称和id。

2.核心代码

NSAttributedStringKey const NSNickNameAttributeName = @"NSNickNameAttributeName";
NSAttributedStringKey const NSUserIDAttributeName = @"NSUserIDAttributeName";
///textView输入内容处理
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    
    if ([text isEqualToString:@""]) {
        
        NSRange selectRange = textView.selectedRange;
        if (selectRange.length > 0 || textView.text.length == 0) {
            //长按或者没有内容
            return YES;
        }
        //判断是否需要删除@内容
        NSInteger index = range.location;
        NSMutableAttributedString *textAtt = [[NSMutableAttributedString alloc] initWithAttributedString:textView.attributedText];
        NSAttributedString *subAtt = [textView.attributedText attributedSubstringFromRange:NSMakeRange(0, index+1)];
        if ([subAtt.string containsString:@"@"] && [subAtt attribute:NSNickNameAttributeName atIndex:index effectiveRange:nil]) {
            NSInteger ans = 0;
            for (NSUInteger i = subAtt.length - 1; i>=0; i--) {
                NSString *tmp = [subAtt.string substringWithRange:NSMakeRange(i, 1)];
                if ([tmp isEqualToString:@"@"]) {
                    ans = i;
                    break;
                }
            }
            [textAtt replaceCharactersInRange:NSMakeRange(ans, index - ans + 1) withString:@""];
            textView.attributedText = textAtt;
            return NO;
        }
        return YES;
    }
    if ((textView.text.length + text.length) >=250) {
        //字数限制
        return NO;
    }
    if ([text isEqualToString:@"@"]) {
        !self.callSomeone?:self.callSomeone();
        
        return YES;
    }
    if ([text isEqualToString:@"\n"]){
        NSMutableArray *atArr = [self checkIfNeedAtSomeoneWithTextView:textView];
        
        if ([_delegate respondsToSelector:@selector(inputToolbar:sendContent:andAtArr:)]) {
            [_delegate inputToolbar:self sendContent:self.textInput.attributedText andAtArr:atArr];
        }
        
        self.textInput.attributedText = nil;
        [self.textInput.delegate textViewDidChange:self.textInput];
        return NO;
    }else
    
    return YES;
    
}

///添加@信息
- (void)changeTextViewWithName:(NSString *)nickname andUserID:(NSString *)userID{
    NSMutableAttributedString *aStr = [[NSMutableAttributedString alloc] initWithAttributedString:self.textInput.attributedText];
    NSMutableAttributedString *bStr = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ", nickname]];
    [bStr setAttributes:@{NSNickNameAttributeName : nickname, NSUserIDAttributeName:userID} range:NSMakeRange(bStr.length - 1, 1)];
    [aStr appendAttributedString:bStr];
    [aStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:17] range:NSMakeRange(0, aStr.length)];
    self.textInput.attributedText = aStr;
}

///查找@内容
-(NSMutableArray *)checkIfNeedAtSomeoneWithTextView:(UITextView *)textView{
    NSMutableArray *atArr = NSMutableArray.array;
    [textView.attributedText enumerateAttributesInRange:NSMakeRange(0, textView.attributedText.length) options:1 usingBlock:^(NSDictionary<NSAttributedStringKey,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
        if (attrs[NSUserIDAttributeName]) {
            NSString *userID = attrs[NSUserIDAttributeName];
            NSString *nickName = attrs[NSNickNameAttributeName];
            if (range.location > nickName.length) {
                NSString *tNickName = [textView.text substringWithRange:NSMakeRange(range.location - nickName.length, nickName.length)];
                NSString *atStr = [textView.text substringWithRange:NSMakeRange(range.location - nickName.length - 1, 1)];
                if ([tNickName isEqualToString:nickName] && [atStr isEqualToString:@"@"]) {
                    [atArr addObject:userID];
                }
            }
        }
    }];
    return atArr;
}

3.总结

网上找了挺多实现方式的,包括图片化@内容、正则判断、记录@内容的位置和信息等,这些方式都不完善且有一定的漏洞,最后只能自己想办法实现了。在这里记录一下,有时间再弄个demo

上一篇下一篇

猜你喜欢

热点阅读