Objective-C how to parse command-line like arguments from a given string?

695 views Asked by At

I'm working with an iOS app using UISearchBar. I would like to add an option for the user to use lightweight search queries that can be entered right in the search bar, like the mail app.

For example, I want to be able to be able to parse "Search Term last:week" and search my data for "Search Term" and create a search filter to show only last 7 days. How can I parse command-line like arguments from iOS String ?

In particular, once I've extracted my tokens and verified that they are valid, how do I remove them from the search query without affecting the rest of the query?

Here's my original attempt. Are there any ready-made tools I can use for this task?

static NSString* whenKeyword = @"when";
static NSString* lastKeyword = @"last";

-(NSMutableDictionary*)findCommandsInQuery:(NSString*)query
{
    //extract keywords from the query, like google mail search. We want to have commands like "cute puppies Last:month"

//remove extra whitespace, prepare to parse
    NSString*  dirtyString = [query stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSArray* tokens = [dirtyString componentsSeparatedByString:@":"];

    //for each token, we want to trim it and remove illegal characters
    NSMutableArray* cleanTokens = [[NSMutableArray alloc] initWithCapacity:tokens.count];
    NSString* token = nil;
    NSString* nextToken = nil;

    NSString* cleanToken = nil;
    for(int i = 0; i< tokens.count; i ++)
    {
        //get a token, for example "cute puppies last"
        token = tokens[i];

        NSArray* words = [token componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        if(words.count >0)
        {
            for(NSString* word in words)
            {
                cleanToken = [DataSource cleanTrimSearchTerm:word];

                if(cleanToken.length > 0)
                {
                    [cleanTokens addObject:cleanToken];
                }
            }

        }else
        {
            cleanToken = nil;
        }



    }

    //process tokens
    NSMutableDictionary* commands = [NSMutableDictionary dictionary];

    for(int i = 0; i< cleanTokens.count; i ++)
    {
        token = cleanTokens[i];
        if(i+1 < cleanTokens.count)
        {
            nextToken = cleanTokens[i+1];
        }
        [self checkToken:token againstKeyword:whenKeyword withQuantifier:nextToken storeInDictionary:commands];
        [self checkToken:token againstKeyword:lastKeyword withQuantifier:nextToken storeInDictionary:commands];

    }
    DLog(@"found commands: %@",commands);
    return commands;
}

Here's a method to respond to commands and create a search query with them

-(void)processCommands:(NSMutableDictionary*)commands
{
    NSString* value = commands[lastKeyword];


    if(value != nil)
    {
        DLog(@"%@" ,value);
        if([value isEqualToString:@"day"])
        {

        }else if ([value isEqualToString:@"week"])
        {

        }else if ([value isEqualToString:@"month"])
        {

        }else if ([value isEqualToString:@"quarter"])
        {

        }else if ([value isEqualToString:@"year"])
        {

        }
    }
}
1

There are 1 answers

0
Julian J. Tejera On

Users usually dislike having to learn query languages. It's a complex user experience. There are many different ways to simplify querying and searching such as using the scope bar of UISearchController or using table view sections to divide the information. But if you are still required to create a query mechanism try to implement your own Abstract Syntax Tree (AST) to avoid spaghetti code