我有大约10-15个检查,我在检查字符串中是否存在子字符串。其中一项检查的示例如下:
if([request.URL.absoluteString.lowercaseString rangeOfString:@"/group/editgroupmembers?groupid"].location != NSNotFound)
我发现通过这些检查需要几秒钟。为了确认,我调试了应用程序,发现每次检查需要1秒以上
rangeOfString
是用于检查子字符串存在的Apple's推荐方法
但为什么需要那么长时间?
答案 0 :(得分:3)
在Apple String Programming Guide中,您还会看到:
如果您只想确定字符串是否包含给定模式,则可以使用谓词:
因此,在您的情况下,您可以使用谓词将您的搜索字符串与您的网址相匹配,从而为您提供更好的效果:
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 ms到500 ms的结果。这是一个典型的输出:
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
虽然这个小基准肯定不是数据独立的,但它表明了两个结果:
filteredArrayUsingPredicate:
,其速度是选项1 rangeOfString:
的两倍。选项2,在迭代不同的字符串时直接使用NSPredicate
,执行情况比选项3稍差。答案 1 :(得分:-1)
如果您要检查网址中的子字符串,那么您可以尝试NSURLComponents
。
NSURLComponents *urlComponents = [NSURLComponents componentsWithString:request.URL.absoluteString];
if ([urlComponents.path rangeOfString:@"/group/editgroupmembers"].location != NSNotFound) {
for (NSURLQueryItem *item in urlComponents.queryItems) {
if ([item.name isEqualToString:@"groupid"]) {
//your code goes here...
break;
}
}
}
试试这个并告诉我这是否改善了性能。感谢。