在iOS中常规的字符串操作方法也没有使用多少种这里列举一下当前需求用到的
API_1.字符串value替换某个range内的字符串,
value = [value stringByReplacingCharactersInRange:range withString:repleaseStr];
API_2.判断inputStr中是否包含Totalname的字符串
BOOL status = [inputStr containsString:totalName];
API_3.获取nameTotal字符串在字符串value中的具体位置对应的range,这里只会匹配到第一次的值,举例来说:
在字符串中包含两次满足匹配条件的,,这正是当前需求所需要的效果
NSRange range = [value rangeOfString:nameTotal];
API_4.截取valueInput字符串中的range范围内的内容,赋值给textString
NSString * textString = [valueInput substringWithRange:range];
需求的图示效果:
display.png需求内容
输入表情包和文字混合的时候需要将表情包对应的表情给展示出来,在数据层面一个笑的表情包可能对应的关键字就是 "[大笑]" 但是需要在展示出来的时候,对用户输入的内容和表情包进行匹配,如果匹配到了对应的表情包,那么将关键字替换成对应的小图标做展示
整个需求来看最费工夫的就是对用户输入的字符串做匹配表情,分割,重新组合的处理
举个栗子:
如果表情包的数组中包含"再见","笑哭","哈哈",那么用户在输入了如下的字符串之后
"你说的这是[笑哭]哈哈镜吧你说的额真是令人难受[再见]啊哈[再见]"
开发者应该做一些处理,处理结果就是将字符串分割成数组,数组内容应该包含一些对象,这些对象是分割字符串所获得,对象中需要包含是否是表情,对象的名字,对象的表情下标
第一步:数据准备
这里数据处理过程中使用了一个类来表示: YZNeedSubModel
@interface YZNeedSubModel : NSObject
@property(nonatomic,assign)NSRange range;//当前对象的字符串范围
@property(nonatomic,strong)NSString * emjName;//当前对象的字符串,如果是文本就是文本内容,如果是表情,就是表情的名字
@property(nonatomic,assign)NSInteger emojIndex;//当前对象对应的表情数组中的下标,如果是纯文本,默认值是-1
@end
输出的类的model:YZMessageModel
@interface YZMessageModel : NSObject
@property(nonatomic,assign)BOOL emoj; //当前对象是否是表情
@property(nonatomic,strong)NSString * name; ////当前对象的字符串,如果是文本就是文本内容,如果是表情,就是表情的名字
@property(nonatomic,assign)NSInteger emojIndex;当前对象对应的表情数组中的下标,如果是纯文本,默认值是-1
@end
第二步:判断字符串是否仍然包含表情包数据
NO表示仍然有表情包在用户输入的字符中,YES表示没有
-(BOOL)judgeContain:(NSArray *)emojArray inputStr:(NSString *)inputStr {
NSLog(@"%@ %@",emojArray,inputStr);
for (int i = 0; i < emojArray.count;i ++) {
NSString * name = emojArray[i];
NSString * totalName = [NSString stringWithFormat:@"[%@]",name];
if ([inputStr containsString:totalName]) {
return NO;
}
}
return YES;
}
第三步:将所有的表情包取出并且获得它们的下标和在总字符串中所占据的range
匹配到的表情包放在needReplaceArray,并且将对应的range范围的字符串替换成相等长度的*,接下来继续执行while循环,使用范围替换的目的是为了使重复的字符也可以被获取到,而不是全局替换导致重复表情被错误的忽略掉,这里范围的获取见上文的API_3
NSMutableArray * needReplaceArray = [NSMutableArray arrayWithCapacity:0];
while (![self judgeContain:self.emojArray inputStr:value]) {
for (int i = 0;i < self.emojArray.count; i ++) {
NSString * name = self.emojArray[i];
NSString * nameTotal = [NSString stringWithFormat:@"[%@]",name];
if ([value containsString:nameTotal]) {
NSRange range = [value rangeOfString:nameTotal];
YZNeedSubModel * model = [[YZNeedSubModel alloc] init];
model.range = range;
model.emojIndex = i;
model.emjName = name;
NSString * repleaseStr;
for (int o = 0; o < range.length; o ++) {
if (repleaseStr.length > 0) {
repleaseStr = [NSString stringWithFormat:@"%@*",repleaseStr];
}else {
repleaseStr = @"*";
}
}
value = [value stringByReplacingCharactersInRange:range withString:repleaseStr];
[needReplaceArray addObject:model];
}
}
}
NSLog(@"用户输入的内容中包含的所有的表情包的数组:%@",needReplaceArray);
第四步:对从字符串中提取出来的表情包数组进行排序
needReplaceArray数据的获取是根据表情包数组emojArray的顺序遍历获取到的,因此needReplaceArray需要根据每个对象的location进行排序来保障实际的展示顺序和位置
NSArray * arrayNeed = [needReplaceArray sortedArrayUsingComparator:^NSComparisonResult(YZNeedSubModel * obj1, YZNeedSubModel * obj2) {
if (obj1.range.location < obj2.range.location) {
return NSOrderedAscending;
}else {
return NSOrderedDescending;
}
}];
第五步:表情包和混合输入的文本数据重新组合
组合结果是一个 arrayLast 数组,目的是将原有的字符串和表情从下标0拼接到输入的字符串的总长度,并分割成数组
NSMutableArray * arrayLast = [NSMutableArray arrayWithCapacity:0];
NSMutableArray * arrayEmoj = [NSMutableArray arrayWithArray:arrayNeed];
NSInteger currentLocation = 0;
NSInteger totalStringLength = valueInput.length;
NSInteger currentEmojIndex = 0;
NSInteger emojTotalCount = arrayEmoj.count;
while (currentLocation < totalStringLength) {
if (currentEmojIndex < emojTotalCount) {
YZNeedSubModel * model = arrayEmoj[currentEmojIndex];
if (model.range.location > currentLocation) {
NSRange range = NSMakeRange(currentLocation, model.range.location - currentLocation);
currentLocation = model.range.location;
NSString * textString = [valueInput substringWithRange:range];
YZMessageModel * modelM = [[YZMessageModel alloc] init];
modelM.name = textString;
modelM.emoj = NO;
modelM.emojIndex = -1;
[arrayLast addObject:modelM.mj_keyValues];
}else if(model.range.location == currentLocation){
YZMessageModel * modelM = [[YZMessageModel alloc] init];
modelM.name = model.emjName;
modelM.emoj = YES;
modelM.emojIndex = model.emojIndex;
[arrayLast addObject:modelM.mj_keyValues];
currentLocation += model.range.length;
currentEmojIndex ++;
}
}else {
NSRange range = NSMakeRange(currentLocation, totalStringLength - currentLocation);
NSString * textString = [valueInput substringWithRange:range];
YZMessageModel * modelM = [[YZMessageModel alloc] init];
modelM.name = textString;
modelM.emoj = NO;
modelM.emojIndex = -1;
[arrayLast addObject:modelM.mj_keyValues];
currentLocation += range.length;
}
}
NSLog(@"arrayLast info = %@",arrayLast.mj_JSONString);
第六步:整体实现的输入和输出结果展示
内容输入输出和图示1
//输入
NSString * valueInput = @"你说的这是[笑哭]哈哈镜吧你说的额真是令人难受[再见]啊哈[再见]";
//输出
[{"emoj":false,"name":"你说的这是","emojIndex":-1},{"emoj":true,"name":"笑哭","emojIndex":1},{"emoj":false,"name":"哈哈镜吧你说的额真是令人难受","emojIndex":-1},{"emoj":true,"name":"再见","emojIndex":0},{"emoj":false,"name":"啊哈","emojIndex":-1},{"emoj":true,"name":"再见","emojIndex":0}]
图示:
first.png
内容输入输出和图示2
//输入
NSString * valueInput = @" [笑哭] 你说的这是哈哈 镜吧你说的额真是令人难受";
//输出
[{"emoj":false,"name":" ","emojIndex":-1},{"emoj":true,"name":"笑哭","emojIndex":1},{"emoj":false,"name":" 你说的这是哈哈 镜吧你说的额真是令人难受","emojIndex":-1}]
图示
last.png
接下来就可以根据最终获得到的对象数组arrayLast来区分展示textString和表情包内容了
总的来讲使用的都是Apple提供的基础方法,只是根据自己的业务需求实现了一个功能,常规操作.
demo下载地址:https://gitee.com/xgkp/stringsub.git
网友评论