ios - NSString rangeOfString 执行缓慢

标签 ios objective-c nsstring

我有大约 10-15 次检查,我正在检查字符串中是否存在子字符串。其中一项检查的示例如下:

if([request.URL.absoluteString.lowercaseString rangeOfString:@"/group/editgroupmembers?groupid"].location != NSNotFound)  

我发现通过这些检查需要几秒钟。为了确认,我调试了应用程序,发现每次检查都需要 1 秒以上的时间。
rangeOfStringApple's检查子字符串是否存在的推荐方法。
但为什么需要这么长时间?

最佳答案

Apple String Programming Guide您还将阅读:

If you simply want to determine whether a string contains a given pattern, you can use a predicate:

因此,在您的情况下,您可以使用谓词将您的搜索字符串与您的网址进行匹配,这应该会给您带来更好的性能:

NSString *path = @"/group/editgroupmembers?groupid";
NSPredicate *containsPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", path];

BOOL match = [containsPred evaluateWithObject:request.URL.absoluteString.lowercaseString];

您可以在 Apple Predicate Programming Guide 中阅读有关谓词的更多信息.

编辑

我做了一个快速基准测试来检查各种选项的性能。

  • 第一个选项是使用 rangeOfString:正如 OP 所做的那样。
  • 第二个选项是使用 NSPredicate .
  • 第三个选项将所有字符串放入一个数组中并使用filteredArrayUsingPredicate: 匹配整个数组。 .

基准测试将 100k 个随机数字字符串放入一个数组中,并使用不同的选项检查匹配短语“123”。这是基准代码:

- (void)benchmarkStringContainment {

    // Setup of array to search through
    NSMutableArray *arrayOfRandomStrings = [NSMutableArray array];
    for (int i = 0; i < 100000; i++) {
        NSString *stringToSearch = [NSString stringWithFormat:@"%lli", arc4random() % 100000000000];
        [arrayOfRandomStrings addObject:stringToSearch];
    }

    // String we search for
    NSString *matchPhrase = @"123";


    // Method 1: rangeOfSubstring
    NSUInteger matches1 = 0;
    NSDate *date1 = [NSDate date];

    for (int i = 0; i < 100000; i++) {
        BOOL match = ([[arrayOfRandomStrings[i] lowercaseString] rangeOfString:matchPhrase].location != NSNotFound);
        if (match) matches1++;
    }

    double timePassed1_ms = [date1 timeIntervalSinceNow] * -1000.0;
    NSLog(@"Method 1: rangeOfString. Matches: %lu, time taken in ms: %f", (unsigned long)matches1, timePassed1_ms);


    // Setup of NSPredicate
    NSPredicate *containsPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", matchPhrase];

    // Method 2: NSPredicate
    NSUInteger matches2 = 0;
    NSDate *date2 = [NSDate date];

    for (int i = 0; i < 100000; i++) {
        BOOL match = [containsPred evaluateWithObject:arrayOfRandomStrings[i]];
        if (match) matches2++;
    }

    double timePassed2_ms = [date2 timeIntervalSinceNow] * -1000.0;
    NSLog(@"Method 2: NSPredicate. Matches: %lu, time taken in ms: %f", (unsigned long)matches2, timePassed2_ms);


    // Method 3: NSPredicate over NSArray
    NSUInteger matches3 = 0;
    NSDate *date3 = [NSDate date];

    NSArray *filteredArray = [arrayOfRandomStrings filteredArrayUsingPredicate:containsPred];
    matches3 = [filteredArray count];

    double timePassed3_ms = [date3 timeIntervalSinceNow] * -1000.0;
    NSLog(@"Method 3: NSPredicate over NSArray. Matches: %lu, time taken in ms: %f", (unsigned long)matches3, timePassed3_ms);

}

在 iPhone 5 上进行测试(调试)时,样本结果会在 200 毫秒到 500 毫秒左右产生结果。这是一个典型的输出:

2015-03-13 10:49:27.815 so29003576[1413:494702] Method 1: rangeOfString. Matches: 978, time taken in ms: 443.618000
2015-03-13 10:49:28.090 so29003576[1413:494702] Method 2: NSPredicate. Matches: 978, time taken in ms: 272.534013
2015-03-13 10:49:28.309 so29003576[1413:494702] Method 3: NSPredicate over NSArray. Matches: 978, time taken in ms: 217.999041

下一步,我多次重复基准测试(代码未显示),并对不同方法进行平均,以获得更具代表性的结果:

2015-03-13 10:54:01.728 so29003576[1423:495973] Method 1: rangeOfString. Repetitions: 50, average time taken in ms: 449.577812
2015-03-13 10:54:01.731 so29003576[1423:495973] Method 2: NSPredicate. Repetitions: 50, average time taken in ms: 276.818836
2015-03-13 10:54:01.732 so29003576[1423:495973] Method 3: NSPredicate over NSArray. Repetitions: 50, average time taken in ms: 222.459898

虽然这个小基准肯定不是数据独立的,但它表明了两个结果:

  1. 在一堆字符串中找到匹配短语的测试选项中最快的是选项 3,使用 filteredArrayUsingPredicate: ,这是选项 1 的两倍,rangeOfString: .选项 2,使用 NSPredicate直接迭代不同的字符串,比选项 3 的性能稍差。
  2. 基准测试在 100.000 个字符串中搜索匹配短语。正如 @gnasher729 在其中一条评论中指出的那样,OP 在他们的代码中一定有不同的问题,因为即使是最慢的方法也应该在 10 到 15 个 URL 上快几个数量级。

关于ios - NSString rangeOfString 执行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29003576/

相关文章:

iphone - 删除 NSURL : iOS 的最后部分

objective-c - 在Objective-C中替换字符串中的一个字符

ios - 为什么使用 UISearchResultsUpdating 取消按钮后我的表格 View 为空白?

ios - 解码 JSON 响应

ios - 将弱变量分配给强变量时

iphone - 从 UIPicker 中的 plist 字典中对数据进行数字排序

objective-c - SIMBL 在取景器中调配

ios - 使用 Jenkins 构建 iOS 应用程序

ios - 当我的 ViewController 被导航时,AFURLSessionManager 应用程序崩溃了

ios - 二进制表达式 ('int' 和 'NSString' 的无效操作数)