Srikanth Pai Srikanth Pai - 1 year ago 63
Objective-C Question

String parsing in Objective C iOS efficiently

I have a (NSDictionary * record) with keys ATTR1,ATTR2,ATTR3.

I have a dynamic where clause which needs to be applied to a sql lite database. But before constructing the fetch request, the predicate has to be in "ATTR1=%@ AND ATTR2=%@ AND ATTR3=%@" format. Also I have a static string whereClause defined in this format "ATTR1=:ATTR1 AND ATTR2=:ATTR2 AND ATTR3=:ATTR3" (Note : This format is unchangeable. It is defined at the customer's production server). By dynamic I mean that the ":ATTR1" , ":ATTR2", ":ATTR3" should get replaced by the values in the dictionary variable record mentioned above.

So to create a predicate , I need the following String and Array of attributes to be created so that I execute the fetch request.

"ATTR1=%@ AND ATTR2=%@ AND ATTR3=%@"


The solution I found was like below :

NSString * whereClause = @"ATTR1=:ATTR1 AND ATTR2=:ATTR2 AND ATTR3=:ATTR3";
NSArray * primaryTokens = [whereClause componentsSeparatedByString: @":"];
NSUInteger primaryTokenCount = [primaryTokens count];
NSMutableString * finalWhereClause = [[NSMutableString alloc] initWithString:primaryTokens[0]];
NSMutableArray * attributes = [[NSMutableArray alloc]init];
if(primaryTokenCount >1)
for(int i=0;i<(primaryTokenCount-1);i++){
NSArray * secondaryTokens = [primaryTokens[i+1] componentsSeparatedByString: @" "];
NSUInteger secondaryTokenCount = [secondaryTokens count];
if(secondaryTokenCount > 1)
[finalWhereClause appendString:@"%@"];
NSArray * newSecondaryArray = [secondaryTokens subarrayWithRange:NSMakeRange(1,[secondaryTokens count]-1)];
[finalWhereClause appendString:@" "];
[finalWhereClause appendString:[newSecondaryArray componentsJoinedByString:@" "]];
[attributes addObject:secondaryTokens[0]];
[finalWhereClause appendString:@"%@"];
NSLog(@"THE FINAL PARSED STRING IS : %@",finalWhereClause);
NSLog(@"THE FINAL ATTRIBUTES IS : %@",[attributes componentsJoinedByString:@","]);

The above code works . But it has the overhead of using 3 extra arrays and separating by components in every run of the primary loop. Is there an efficient way in Objective C to achieve this parsing so as to avoid this over head of extra storage. This method would be called extensively. Hence any help would be appreciated.

Answer Source
NSString *whereClause = @"ATTR1=:ATTR1 AND ATTR2=:ATTR2 AND ATTR3=:ATTR3";
NSString *finalWhereClause = whereClause;

NSArray *clauseComponents = [whereClause componentsSeparatedByString: @" "];
NSMutableArray *attributes = [NSMutableArray new];

for (NSString *component in clauseComponents) {

    if ([component containsString:@":"]) {

        NSString *paramName = [component substringFromIndex:[component rangeOfString:@":"].location + 1];
        [attributes addObject:paramName];

        NSString *separatedParamName = [@":" stringByAppendingString:paramName];
        finalWhereClause = [finalWhereClause stringByReplacingOccurrencesOfString:separatedParamName withString:@"%@"];



NSLog(@"THE FINAL PARSED STRING IS : %@",finalWhereClause);
NSLog(@"THE FINAL ATTRIBUTES IS : %@",[attributes componentsJoinedByString:@","]);