Finding the cursor position in a UITextField

I am currently writing my first iOS application, Am I A Millionaire. One of the cool features I wanted to implement was to automatically format the currency that a user was entering, using the appropriate region formatting (e.g. commas to separate thousands in the US, and spaces if you were using South African Rand etc)

The code to format on the fly was pretty easy, but there was an issue of the cursor position being reset to the end of the string if you update a UITextField on the fly (e.g. field.text = @”some new value”). In order to get around this, I needed to find out where the cursor was before I changed the text, and then restore it afterwards.

As of iOS 5, this is a non-trivial process. At first it seemed simple – selectedTextRange returns a UITextRange object that has a start and end. Unfortunately, they are UITextPositions, not integers. This in a abstract class that you can’t get the members of to find out the index without violating Apple’s “don’t play with our privates” rule.

Fortunately, since UITextField conforms the UITextInput protocol. So, by comparing the current position to the end position, I was able to get the relative position of the cursor, and then restore it after setting the text. Sample code is below:

    // Get the selected text range
    UITextRange *selectedRange = [self selectedTextRange];

    // Calculate the existing position, relative to the end of the field (will be a - number)
    int pos = [self offsetFromPosition:self.endOfDocument toPosition:selectedRange.start];

    // Change the text
    self.text = lastValidated; 

    // Work out the position based by offsetting the end of the field to the same
    // offset we had before editing
    UITextPosition *newPos = [self positionFromPosition:self.endOfDocument offset:pos];

    // Reselect the range, to move the cursor to that position
    self.selectedTextRange = [self textRangeFromPosition:newPos toPosition:newPos];

Hacky, but it works. This seems to be a common theme with iOS development. I wish Windows Phone 7 had the same audience, as .net is so much better to work with :)

NB: I used the offset from the end, as it was easier to deal with backspace. If the iPhone supported delete, then this code wouldn’t work. Also, it doesn’t work so well when the user selects an actual range and hits backspace.

Excel Tip: How do you create a dynamic reference to a cell and retrieve it’s value

I stumbled across a handy function in Excel today – Indirect(). Basically, it allows you to convert a string into a cell reference. Typically, in excel, if you want the value of a particular cell (say A5), you use the following:

=A5

However, indirect allows you to refer to the same cell, but as a string

=INDIRECT("A5")
=INDIRECT("A" & "5")

This enables you do to some pretty cool things, like let the user choose which column they want to sum:

Example of using Indirect

Creating your own NuGet server

Over the years, I have been compiling little code snippets to perform common tasks – like parsing the filename out of a file path, or adding the ever so useful .With() to the string class (supports “My {0} string {1}”.With(“awesome”, “extension”)). I often find myself opening up old projects to find the code and copying and pasting it into my new project. This leads to a lot of splintered code, and it can be a pain finding the latest version. After watching Scott Hanselman’s latest posts on NuGet, I figured it might help me keep things straight. Creating your own NuGet server is easy – however, getting it to run is a bit more complicated :)

I am not going to reinvent the wheel here, as Phil Haack has done a great job here. Some things to note:

  • You can install this in to an existing website (I added it my website using MVC3)
    • However, be aware it does add a default.aspx that you will want to delete so that people still see your old homepage
  • If you are deploying this to a server that binds multiple sites to the same ip address, make sure to add the following to your web.config
    <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled=true />
    </
    system.serviceModel>
    • Otherwise, you will get errors along the lines of “This collection already contains an address with scheme http”
  • Make sure to add .nupkg to your mime types on IIS (right click properties on the server in IIS MMC)
    • .nupkg application/zip should do it
    • Otherwise, you will get 400 or 404 errors when you try to request your package

Intellisense (AutoComplete) Broken in Sql Server 2008 R2

If your Intellisense in SQL Server Management Studio just stopped working, chances are you have applied Visual Studio 2010 SP1. This is because there is a compatibility issue between Microsoft SQL Server 2008 R2 Management Studio (SSMS 2008 R2) and the Transact-SQL Language Service that is included in Visual Studio 2010 SP1.

The good news is there is a fix included in the latest Cumulative Update package for SQL Server 2008 R2 - http://support.microsoft.com/kb/2507770

All you need to do is download the pack, install it, and go back to saving your keystrokes.

Getting Visual Studio Key Mappings in Eclipse

Over the last few weeks I have been writing my first Android app in Java (more details will come once it released – hush hush right now). While Eclipse has improved a lot since I last used in (back in 2003 or so), I have found the experience reasonably frustrating coming from the nicely polished Visual Studio 2010.

While most of these things are just a matter of switching from KoolAid back to plain old rusty tap water, there’s one thing that bites me time and time again – different key mappings! Fortunately, it’s actually pretty easy to change your mappings to be more “Visual Studio” like.

First of all, you need to install the C/C++ Development Tools – Help > Install New Software

Install the C++ developer tools

Once you restart the environment, go to Window > Preferences > General > Keys and set your Scheme to “Microsoft Visual Studio”

Set your scheme to Visual Studio

How to speed up Test Manager

I think we’re one of the only users of Microsoft’s Test Manager (MTM) – it’s actually a pretty amazing application for testing applications once you get used to it’s quirky UI. However, it can be very slow when running tests (even when you don’t choose “create action recording”) – for example, your mouse actions end up being jerky, and typing can be very unresponsive/bursty. The reason for this is that there are a lot of Trace Diagnostics that are running by default. We don’t use any of that information, so we turn it off. How does one do this?

  • First of all, go to Plan then select your root node and hit “Properties”
  • Create a new Manual Run Test Settings Configuration
  •  Go to Data and Diagnostics, and clear all the traces you don’t need
  • You will now use these settings by default when you hit Run
  • Bask in the speed of it all

TFS: Description HTML field is Read Only in Excel

We have recently moved towards using Team Foundation Sever (TFS) as our main collaboration environment. Previously, we had been just using it for Source Control and tracking bugs in Fogbugz. TFS has several advantages, which I will get into in another post, but there are a lot of quirks.

One of the things I found great, then annoying, with TFS is the ability to edit all the work items in Excel. We used this for creating our initial backlog, populating the Description HTML field with descriptions of the use case. However, when I went back to edit them, I found out that HTML items are only editable in Excel when you first create them. We don’t use the HTML abilities of the Descrpition, so we decided to switch to just the “plain text” version of description instead.

WARNING: Do this in a test project first, so you know what you are getting yourself into.

So I cracked out my trusty text editor and started editing the product workflow item XML – I’ll cover this in more detail later, but what you need to do is this:

(Command Prompt in  C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE)
witadmin exportwitd /collection:http://yourcollection/tfs /p:ProjectYouAreChanging /n:"Product Backlog Item" /f:productbacklogitem.xml

Now open up the xml file in your trusty editor and change the line:

<Control FieldName="Microsoft.VSTS.Common.DescriptionHtml" Type="HtmlFieldControl" Label="" LabelPosition="Top" Dock="Fill" />

to

<Control FieldName="System.Description" Type="HtmlFieldControl" Label="" LabelPosition="Top" Dock="Fill" />

Now import your new Work Item Definition:

witadmin importwitd /collection:http://yourcollection/tfs /p:ProjectYouAreChanging /f:productbacklogitem.xml

The HTML Field Control is smart enough to realize that it should only allow text in this field, and when it displays in Visual Studio and Team Web Access, it works like an old-school Textbox control.

It was really easy to update the System.Description field with the old content – just create a custom query of all your backlog items, and select the Description and Description HTML fields. Open the result in Excel, and copy and paste all the data and press Publish.

Another bonus is that the Description Field is indexed, so it should come up in search results (haven’t tested this yet, though).

SetDefault for C# Dictionary / IDictionary

If you have ever written anything in Python, I am sure you have stumbled across the immensly useful “SetDefault” method. Chances are if you came here via search, you know what this means, jump to the implementation – if not, read on.

Background

Basically, SetDefault checks to see if a key exists in a dictionary – if so, it returns the value associate with it. If not, it creates the value, inserts it into the dictionary, and then returns the value. A typical usage would be when you want to cache something – instead of this:

var d = new Dictionary<string, string>();
if (d.ContainsKey("somecachekey"))
{
  return d["somecachekey"];
}
else
{
  string result = SomeMethodToGenerateValue("somecachekey", someOtherStuff);
  d.Add("somecachekey", result);
  return result;
}

SetDefault would allow you to just write:

var d = new Dictionary<string, string>();
d.SetDefault("somecachekey", () => SomeMethodToGenerateValue("somecachekey", someOtherStuff));

The benefit here is rather marginal. However, where this comes into it’s own is when you have Dictionary of Dictionaries, or a Dictionary of Lists. This happens all the time when dealing with trees and tree like structures. Here, your code to add a new node simply becomes:

var children = new Dictionary<string, List<Node>>();
d.SetDefault("left", () => new List<Node>()).Add(childNode);

This code would check to see if there was already a list associated with the key “left” in your collection. If so, it would add the childNode to it; otherwise, it would create a new list and then add the child node to that list.

Even better, .Net allows you create a default instance of a object with Activator.CreateInstance() so you can make things even more succinct with a SetDefault(key) method that will instantiate and return the default instance of TValue if the key doesn’t exist:

var children = new Dictionary<string, List<Node>>();
d.SetDefault(“left”).Add(childNode);

Implementation

Here’s the simple version of the code – you can find the complete source here (including the default instance version): SetDefaultExtension.cs:

public static class SetDefaultExtension
{
  public static TValue SetDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> initFunction)
  {
    TValue result;

    if (!dictionary.TryGetValue(key, out result))
      return dictionary[key] = initFunction();
    return result;
  }
} 

Now, if you use the namespace you’ve given the class all objects that implement IDictionary<TKey, TValue> will now support the .SetDefault method.

For what it’s worth, SetDefault is a weird name, but I’ll stick with conventions.

Microsoft Parallel Extensions – Hard”core” code made easy!

Ok, so I must admit that I was a little disappointed last night. I was really looking forward to implementing a threaded Consumer / Producer to try and take advantage of our 16 core datawarehouse server. Instead, I ended up changing one line of code – welcome to the world of Microsoft Parallel Extensions.

The Background (feel free to skip this)

At my work, it’s really important for us to be able to detect if people are sharing their accounts. We do this via storing a permanent cookie on the users machine with a “Machine ID” (a guid we generate). When they log in from that machine, we log the id so we know the user was on a particular machine. The more machines, the more likely they are sharing their account.

This worked well, apart from the fact that people tend to clear their cookies, leading to an artificial rise of “Machine IDs” over time. Three years ago, I came up with an algorithm to find out how to work out what machine IDs were due to cookie clearing, and what ones weren’t. So I don’t bore you to death with the details, I will leave that for another post.

The Details

At the core of my problem was the following loop:

foreach (string user in userlist)
{
  // Do some stuff
  // Commit it to the database
}

This was going through around 60,000 users and 4mil+ records and running a pretty complex algorithm on them. It took around 10 minutes to run, but when I looked at the performance monitor, I noticed that the total CPU usage rarely got over 4% and that only one CPU process spiked – hmm, a common sign that threads would help :) One of my pet hates is having to write really complicated and unintelligble code just to “increase” performance, and threads, not matter how hard you try, always end up looking ugly!

The Solution

Some neuron at the back of my brain started firing, and I got this feeling that I knew a better way. F# – nope, that’s not it – would be helpful, but it would take me a long time to convert everything into Functional Programming. A quick google search bore fruit: this article I read Microsoft Parallel Extensions library back in 2007! Microsoft are now planning on releasing this as part of .Net 4.0; but a CTP for 3.5 still exists.

After installing the MSI and then adding the reference to System.Threading, all I needed to do was to make this simple change:

Parallel.ForEach(userlist, (username) =>
{
 // Same code as before
});

It was that simple! Voila, multi-threading code. If you want more control over the threads created, you can use the TaskManagerPolicy object – a simple way to do this is outlined here.

Caveat: You’re code inside the loop has to be thread safe – since none of my code was modifying shared objects, this wasn’t a concern for me.

The Result

TaskMonitory

Beautiful! The task now takes under a minute instead of 10.

MarketClose Twitterobot – Step 1: Yahoo!

So, I am a recovering stockoholic. I’ve been out of the markets for about 2 years now, but I am still facsinated by their daily fluctuations. I found myself hovering over the address bar and habitually typing finance.google.com to find out what was happening. But that only satiated my fix when I was firefox. So, I added the keyword “stocks” to slickrun so I could quickly open up finance.google.com from anywhere. Bah – too many keystrokes – I used winkey to assign it to Win+C.  But what to do before 10am? I started checking the future markets before getting to work.

It was too much – I had to go cold turkey! I changed Win+C back to being a command prompt, and re-aliased stocks to take me to proggit. I decided that instead, I would write a simple C# program to send me the stock price at the end of the day. I’ve been meaning to play around with the Twitter API for a while now, so it finally gave me an excuse.

However, before the fun started, I first had to get the data.

Step 1 – Yahoo!

Yahoo have a nice little rest based CSV generation system for stock quotes. Basically, all you need to do is request urls in the following format:

http://download.finance.yahoo.com/d/quotes.csv?s=ticker1+ticker2&f=othercomands

The s query string parameter defines the tickers you want to retrieve (separated by spaces) and the f defines what fields you want back – you can find a listing of all those commands here.

So, for my needs, I just needed to request:

http://download.finance.yahoo.com/d/quotes.csv?s=^IXIC+^DJI+^GSPC&f=sl1o

Fortunately, .net makes rest request a piece of cake:

using (WebClient wc = new WebClient())
{
   
return wc.DownloadString(@”http://download.finance.yahoo.com/d/quotes.csv?s=^IXIC+^DJI+^GSPC&f=sl1o”);
}

So all that was left to do was to write something to quickly parse the csv (unit tests are your friend for things like this) and to move some things out to config files (such as the url)

Next Step – Twitter!

Follow

Get every new post delivered to your Inbox.