美文网首页
-[__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