美文网首页
-[__NSCFString deleteCharactersI

-[__NSCFString deleteCharactersI

作者: Sunday_David | 来源:发表于2018-09-12 11:27 被阅读0次

写在前面

  • 急着解决当前问题的开发同学,可以跳过,直接看后面的解决方法

场景

  •  需求: 有一个字符串:@"今天我们来学习NSCharacterSet我们快乐",去除字符串中所有的@"今"、@"我"、@"s"、@"S"。
    

错误做法

    NSString *str = @"今天我们来学习NSCharacterSet我们快乐";
    NSString *str1 = @"我sS今";
    
    NSMutableString *resultStr = [NSMutableString stringWithString:str];
    
    for (int i = 0; i < str.length; i++) {
        NSRange indexRange = NSMakeRange(i, 1);
        NSString *indexStr = [str substringWithRange:indexRange];
        if ([str1 containsString:indexStr]) {
            
            if (indexRange.location != NSNotFound) {
                NSLog(@"str.length = %lu",str.length);
                NSLog(@"resultStr.length = %lu",resultStr.length);
                NSLog(@"indexRange = %@",NSStringFromRange(indexRange));
                [resultStr deleteCharactersInRange:indexRange];
            }
        }
    }

报错

2018-09-12 03:46:23.686670+0800 NSCharacterSet[2414:36081] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString deleteCharactersInRange:]: Range or index out of bounds'
         *** First throw call stack:
         (
         0   CoreFoundation                      0x00007fff471482db __exceptionPreprocess + 171
         1   libobjc.A.dylib                     0x00007fff6e2e9c76 objc_exception_throw + 48
         2   CoreFoundation                      0x00007fff471d9d7d +[NSException raise:format:] + 205
         3   CoreFoundation                      0x00007fff47187945 mutateError + 261
         4   NSCharacterSet                      0x0000000100000ded main + 445
         5   libdyld.dylib                       0x00007fff6ef03015 start + 1
         6   ???                                 0x0000000000000001 0x0 + 1
         )
         libc++abi.dylib: terminating with uncaught exception of type NSException
         (lldb)

原因分析

  • 最直接的,新建一个Demo工程,是把我上面的代码复制进去运行,可以看到控制台的打印。

  • 分析:可变字符串长度resultStr.length的数值是不断变化(减少)的,因为你一边遍历,一边删除。resultStr.length在减少,但你删除用的是长度不变的str.length的indexRange,这就很容易产生越界的crash

解决方法

方法一

  • 使用可变字符串的长度resultStr.length
        for (int i = 0; i < resultStr.length; i++) {
// 方法一,用变化(可变字符串)的字符串(resultStr)的长度

方法二(推荐)

  • 逆序遍历
  • 逆序遍历可以减少开发中很多越界问题,通用性很强
  • 代码如下:
    • 把遍历的地方改成下面的
for (int i = (int)str.length - 1 ; i >= 0; i--) {
// 方法二,使用原来的字符串(str.length)。 (强制转换(int),可去除警告⚠️:Implicit conversion loses integer precision: 'unsigned long' to 'int')

方法三

  • 删除 -> 添加
    NSString *str = @"今天我们来学习NSCharacterSet我们快乐";
    NSString *str1 = @"我sS今";
    
    NSMutableString *resultStr = [NSMutableString string];
    
   for (int i = 0; i < str.length; i++) {
   
        NSRange indexRange = NSMakeRange(i, 1);
        NSString *indexStr = [str substringWithRange:indexRange];
        
        if (![str1 containsString:indexStr]) { 
             // 方法三,创建一个新的可变字符串,删除操作改为添加操作 
            [resultStr appendString:indexStr];
        }
    }

方法四

  • 使用NSCharacterSet
    NSString *str2 = @"今天我们来学习NSCharacterSet我们快乐";
    NSCharacterSet *characterSet = [NSCharacterSet characterSetWithCharactersInString:@"我sS今"];
    NSArray *setArray = [str2 componentsSeparatedByCharactersInSet:characterSet];
    NSLog(@"setArray = %@", setArray);
    NSString *resultStr2 = [setArray componentsJoinedByString:@""];
    NSLog(@"resultStr2 = %@", resultStr2);

方法五

  • 字符串转化为数组,使用Block遍历enumerateObjectsUsingBlock

方法N

  • 欢迎补充

相关文章

网友评论

      本文标题:-[__NSCFString deleteCharactersI

      本文链接:https://www.haomeiwen.com/subject/nphvgftx.html