Magic of NSLinguistic​Tagger

This evening one of my friends sent me the link of iA Writer’s video featuring their latest update to the app.

I was blown away by the syntax highlighter in edit mode, where it highlights words based on selection of parts of speech.

At first, I thought they are doing some sophisticated natural language processing, I’m not expert but supporting multiple languages sounds like a tedious/impossible job to do in an year, unless there is easy way.

Apple provides us NSLinguistic​Tagger class as part of the iOS 5 SDK, it allows us to split up natural language text and tag it with information. As per the documentation it can identify languages, scripts and stem forms of words! NSLinguistic​Tagger is quite easy to use.

We can start by creating the instance of NSLinguisticTagger with tag schemes for a language and bunch of NSLinguisticTaggerOptions, options are used to tell tagger to ignore words, white spaces, punctuations etc.

var options = NSLinguisticTaggerOptions.JoinNames 
              | NSLinguisticTaggerOptions.OmitWhitespace;

var tagger = new NSLinguisticTagger (
    NSLinguisticTagger.GetAvailableTagSchemesForLanguage ("en"), 
    options);

Once we create the instance, we will assign it a string to analyse

tagger.AnalysisString = "A quick movement of the enemy will jeopardise six gunboats";

And finally, fetch the tags with EnumerateTagsInRange method and print them out.

tagger.EnumerateTagsInRange (new NSRange (0, statement.Length), NSLinguisticTag.SchemeLexicalClass, options, TaggerEnumerator);

...

void TaggerEnumerator (NSString tag, NSRange tokenRange, NSRange sentenceRange, ref bool stop)
{
    var word = statement.Substring (tokenRange.Location,
      tokenRange.Length);
    words.Add (new Tuple<string, string> (tag, word));
}

The result after processing A quick movement of the enemy will jeopardise six gunboats looks something like this:

 Adjective: quick
 Noun: movement, enemy, gunboats
 Preposition: of
 Verb: will, jeopardise
 Number: six

it even identifies the number, that’s pretty amazing!

PS: You can find the complete code here – https://gist.github.com/prashantvc/8039121

Modal UIAlertView (iOS 7)

It’s common practice to use NSRunLoop to show modal UIAlertView to block code execution until user input is processed in iOS.

The below code worked perfectly on previous versions of iOS (5 & 6)

int ShowModalAletView (string title, string message, params string[] buttons)
{
    int clicked = -1;
    var alertView = new UIAlertView (title, message, null, null, buttons);
    alertView.Show ();
    bool done = false;
    alertView.Clicked += (sender, buttonArgs) => {
        Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
        clicked = buttonArgs.ButtonIndex;
    };
    while (clicked == -1){
        NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
    }
    return clicked;
}

until Apple released the iOS7, it broke few existing apps 1. Fortunately, there is a better way of implementing it with C#’s async/await

Here’s the new code taking advantage of async/await pattern to show modal UIAlertView:

Task ShowModalAletViewAsync (string title, string message, params string[] buttons)
{
    var alertView = new UIAlertView (title, message, null, null, buttons);
    alertView.Show ();
    var tsc = new TaskCompletionSource ();

    alertView.Clicked += (sender, buttonArgs) => {
        Console.WriteLine (“User clicked on {0}”, buttonArgs.ButtonIndex);
        tsc.TrySetResult(buttonArgs.ButtonIndex);
    };
    return tsc.Task;
}

//Usage
async Task PromptUser() {
    var result = await ShowModalAletViewAsync (“Alert”, “Do you want to continue?”, “Yes”, “No”); //process the result
}

  1. From Apple Developer Forum: https://devforums.apple.com/message/887792