MonoTouch Programming in Visual Studio

TL;DR

Never underestimate the little time sinks of switching between IDEs regularly. To write MonoTouch code in Visual Studio 2010 (debug/deploy still requires MonoDevelop on a Mac), go get VSMonoTouch. If you have any issues getting it going, you may need to toss in some project file tweaks.

Background

I’ve been programming with MonoTouch for a few months now using MonoDevelop. I really enjoy learning new things (even if MonoTouch saved me from learning Objective-C), but switching IDEs always tosses a few kinks in my productivity. I have tweaked a number of key bindings in MonoDevelop to match Visual Studio, some at the cost of my ability to adapt to the Mac’s defaults that are normally used everywhere. At one point I switched copy and paste to use Ctrl in MonoDevelop, but then I kept screwing up outside of the IDE. Regardless, I have become fairly productive in MonoDevelop from simply adapting to the new system through repetition (often screwing up when I switch back to Windows now).

I don’t really have a problem with MonoDevelop most days, but I definitely prefer the Windows system of maneuvering windows and working on multiple displays. Even if I were a Mac-only person, I would hate how full-screen mode works on a Mac. While I have adapted to my new MonoDevelop workflow, I definitely miss having multiple tabs open in a single project; to open multiple instances of MonoDevelop on a Mac, you even need a simple hack. Having to flip around between MonoDevelop and Chrome as I drink from the MonoTouch learning firehose only compounds the window management issue.

Nothing seems to get you around the need for a Mac when testing/debugging/deploying a MonoTouch project, but having Visual Studio as your primary IDE for all your .NET projects can definitely speed things up.

VSMonoTouch

Enter VSMonoTouch by Jonas Follesø (follesoe on GitHub).

This Visual Studio VSIX add-in (warning: requires a non-free Visual Studio) seems to create a system for allowing Visual Studio to recognize the MonoTouch framework and its project type and use the correct DLLs for compiling. For simplicity’s sake, just follow the instructions in the project README for your first run. If that doesn’t work, start looking for tweaks.

The final process I used was simply moved the VSIX install step from first to last on the instructions list from the README (with absolutely no reason to explain why it worked). Regardless, feel free to try some restarts on the off chance you have issues.

  1. Copy the MonoTouch binaries from your Mac development environment to your Visual Studio 2010 development environment. Copy all the files from /Developer/MonoTouch/usr/lib/mono/2.1/ on your Mac to C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v1.0 on your PC.
  2. Add a RedistList-folder under your newly created v1.0-folder. Download the FrameworkList.xml file and add it to the RedistList-folder.
  3. Download and run the vsix-package from the github page.

Code Reference Quirks

It seems that some systems have an easier time getting VSMonoTouch to run than others. On my Windows 7 machine with Visual Studio 2010 (10.0.40219.1 SP1Rel), .NET 4.5, and various Visual Studio 2012 free components; I had a few issues getting things just right. The first three times I tried things out, I simply couldn’t get Visual Studio to acknowledge the project type. It would load the solution I have from MonoDevelop but leave the projects unloaded.

I tried all sorts of variations on the FrameworkList.xml file and gave up for a while.

mscorlib

Today, I decided to try again after I noticed a few updates to a project issue with mscorlib. That wasn’t the issue I was having, but I was hoping anyone trying to solve this issue may accidentally find a solution to help my problem. Oddly, after installing the DLLs first and then the VSIX, it all started loading correctly but with some compile errors and warnings.

  • Error: “An assembly with the same identity ‘mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’ has already been imported. Try removing one of the duplicate references.”
  • Warning: “No way to resolve conflict between “mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089” and “mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”. Choosing “mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ arbitrarily.”
  • Warning: “There was a mismatch between the processor architecture of the project being built “MSIL” and the processor architecture of the reference “C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll”, “x86″. This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.”
  • Warning: “Found conflicts between different versions of the same dependent assembly.”

This is where that [mscorlib project issue] came into play. There was a note on the VSMonoTouch README about making sure to have explicit mscorlib references, but I already did. Checking the box on the “Do not reference mscorlib.dll” project property, though, removed those errors.

VSMonoTouch mscorlib.dll issue fix

If you are a fan of tweaking csproj XML directly instead of through the project properties editor, feel free to add this node to any compilation PropertyGroups manually.

<NoStdLib>true</NoStdLib>

System.Web.Services

After fixing the mscorlib.dll issues, though, I got a new error popping up. This final compile error was coming from code I wrote, so that was a good sign (I guess).

  • Error: “The name ‘HttpUtility’ does not exist in the current context”

Since I am writing an application that interfaces almost entirely with the web-based JSON API I wrote, there are a few places where I am sending back user content to that system. The URL encoding I use simply hits HttpUtility.UrlEncode. In MonoTouch, you need to make sure you reference System.Web.Services to get UrlEncode. But, in Visual Studio Land, the .NET 4.0+ DLL doesn’t have such a method. You can fix this issue with a static version reference on that DLL. There may be a version-agnostic way to do this, but I ended up editing my csproj file to point to the specific version found in the MonoTouch DLLs.

<Reference Include="System.Web.Services, Version=2.0.5.0" />

I will probably have to update this manually whenever a new version hits MonoTouch, but I definitely can live with that.

VSMonoTouch In Use

After getting the loading and compile errors worked out, I now have a MonoTouch solution building successfully in Visual Studio 2010. It contains a core project shared with the Sierra Trading Post Android app (using a few compiler directives) and my MonoTouch project containing almost entirely UI-related code. I write some code and it tells me whether it will compile correctly against the MonoTouch DLLs. I haven’t tried abusing the reliability of this system with any features that are not part of Mono (e.g., async/await) or MonoTouch (e.g., dynamic) yet.

Since my project is currently synced through Dropbox, I just save what I have on Windows and roll on over to the MacBook to run things on the simulator or deploy them to a physical device and/or TestFlight (which is far better than sliced bread, at least for getting your app out to multiple devices). MonoDevelop will even automatically update your project files if you already have it open, though I don’t recommend editing on both systems simultaneously without having something between them to handle conflicts that are bound to arise.

Creating an animated spinner in a Xamarin.iOS (MonoTouch) UIImageView

Background

I’m well into my first week of building the Sierra Trading Post first iOS app using Xamarin.iOS and it has been a fun ride so far. One of the first things needed was a system for showing a loading image while asynchronously retrieving the final image with a web request.

Attempt 1

Xamarin has a recipe for using a UIImageView‘s AnimationImages to make a spinner.

UIImageView someImageView = new UIImageView();
someImageView.AnimationImages = new UIImage[] {
    UIImage.FromBundle("Spinning Circle_1.png"),
    UIImage.FromBundle("Spinning Circle_2.png"),
    UIImage.FromBundle("Spinning Circle_3.png"),
    UIImage.FromBundle("Spinning Circle_4.png"),
};
someImageView.AnimationRepeatCount = 0; // Repeat forever.
someImageView.AnimationDuration = 1.0; // Every 1s.
someImageView.StartAnimating();

It may be possible to make this work, but it wasn’t quite what I needed. This seems to be more of an image rotation than an animation. As a result, it creates a jerky animation between the various images equally distributed over the AnimationDuration you set.

After this, attempts to find some ideas for a better solution lead me to about a hundred lines of code that proved a difficult to consume, involving a CGBitmapContext and CGAffineTransform.MakRotation. (To be fair, this code isn’t doing something as simple as what I want to do.) Hoping to avoid that, I simply added four more rotation positions into the list. It would probably take many more to make it appear smooth. Any more than that and I really didn’t want to bloat my project with minute rotations of the same PNG. Back to Google I went.

Solution

After enough poking around some slightly related Google results, I began to understand enough of CABasicAnimation to see how it could work for the job. You create the desired animation and add an instance of UIImageView.Layer.

    // Image to be rotated (in this case, found in the project as "/Assets/Images/loading_icon.png").
    UIImageView someImageView = new UIImageView(UIImage.FromBundle("Assets/Images/loading_icon"));
    CABasicAnimation rotationAnimation = CABasicAnimation.FromKeyPath("transform.rotation");
    rotationAnimation.To = NSNumber.FromDouble(Math.PI * 2); // full rotation (in radians)
    rotationAnimation.RepeatCount = int.MaxValue; // repeat forever
    rotationAnimation.Duration = 1;
    // Give the added animation a key for referencing it later (to remove, in this case).
    someImageView.Layer.AddAnimation(rotationAnimation, "rotationAnimation");

The main part of this is the simple rotation CABasicAnimation that is applied to a Layer of a UIImageView. In this case, it is set to do a full rotation (accepted in radians) every one second through a very large number of repetitions. The repetitions is actually one oddity in the switch to this new method. When you set UIImageView.AnimationRepeatCount, you can set it to zero to make it loop forever. Oddly, a CABasicAnimation.RepeatCount set to zero is the same as one, and it loops a single time before stopping.

Code (Example doing for a bunch of UITableView cells)

static NSString key = new NSString("somecellkey");
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) {
    UITableViewCell cell = tableView.DequeueReusableCell(key);
    if (cell == null) {
        cell = new UITableViewCell(UITableViewCellStyle.Default, key);
    }

    // Image to be rotated (in this case, found in the project as "/Assets/Images/loading_icon.png").
    cell.ImageView.Image = UIImage.FromBundle("Assets/Images/loading_icon");
    CABasicAnimation rotationAnimation = CABasicAnimation.FromKeyPath("transform.rotation");
    rotationAnimation.To = NSNumber.FromDouble(Math.PI * 2); // full rotation (in radians)
    rotationAnimation.RepeatCount = int.MaxValue; // repeat forever
    rotationAnimation.Duration = 1;
    // Give the added animation a key for referencing it later (to remove, in this case).
    cell.ImageView.Layer.AddAnimation(rotationAnimation, "rotationAnimation");

    // Do your lazy-loading of the image (blog post coming soon...maybe).
    ...

    // For a good time, you can keep rotating your final, lazy-loaded image by not calling this line.
    cell.ImageView.Layer.RemoveAnimation("rotationAnimation");

    // Do the rest of your visual stuff to the cell.
    ...

    return cell;
}

More Code

If you want a quick demo application of the differences, check out the GitHub repo I put together [and finally got around to sharing]. It is a simple demo of two UIImageViews that implement the two methods here. Clicking anywhere will toggle between the two.

Here’s a quick video snippet of the demo code running.

Mono for Android: “aapt.exe” exited with code 1

TL;DR

Also available in TL;SO (too long; Stack Overflow) flavor.

Getting this error: "aapt.exe" exited with code 1?

Do you have any files in your Mono for Android solution that are being packaged together with the app (e.g., “AndroidResource” build action)?

If so, make sure they don’t have anything but letters, numbers, periods, and underscores ([a-z0-9_.]) in their names.

Details

I am still getting my feet wet with Mono for Android (MfA) development. One of my first projects was a flashlight app for my Galaxy Nexus that introduced me to a couple Android/MfA development quirks. One concept in app development that I would like to explore is long-running tasks. How do I keep something going after the user has switched off to something else?

Greg Shackles has a new Visual Studio Magazine article on Background Services in MfA on just that topic. He creates a background service for playing an MP3 file using a standard Android service.

In his sample project, he sets up the service to play some Creative Commons Nine Inch Nails music.

I happen to have a good collection of my own Nine Inch Nails music. As I put the code together in my own project, I grabbed one such MP3 file, named “02 1,000,000.mp3”, and added it with the “AndroidResource” Build Action. Unfortunately, hitting Ctrl+Shift+B resulted in a lovely error: "aapt.exe" exited with code 1.

If you go to the Visual Studio output window, you don’t find much else of value.

Fortunately, you can get more verbose output from MSBuild if you ask for it. In the Visual Studio Options, go to “Projects and Solutions” then “Build and Run”. Switch the “MSBuild project build output verbosity” from “Minimal” to “Normal”. After I built the project again, I got a little clearer message: res\raw\02 1,000,000.mp3: Invalid file name: must contain only [a-z0-9_.].

A quick name change to something within the [a-z0-9_.] range and the project built beautifully. While this new sample project is just a horrible version of the baked-in music application, that definitely isn’t the point. It is definitely nice to have some code written about a concept before you find yourself needing it the first time.

Where did that JSON field go? Serializing IHtmlString to JSON.

TL;DR

If your brain consumes Stack Overflow questions better than blog posts, go see “How do I serialize IHtmlString to JSON with Json.NET?” over there.

IHtmlString doesn’t play nicely with JSON serialization

If you have an IHtmlString in your JSON (regardless of arguments against putting raw HTML in JSON), you will probably need to customize the serialization to get the HTML out of that variable. In fact, the serialization will probably be invalid compared to what you expect; it does make sense if you think about how the serialization process works.

Fortunately, putting together a quick Json.NET JsonConverter will make the issue go away.

What you might expect from some object containing an IHtmlString variable named x:

{ x = "some <span>text</span>" }

What default .NET JavaScript serialization and default Json.NET serialization will give you for said object:

{ x = { } }

How to fix it with Json.NET:

public class IHtmlStringConverter : Newtonsoft.Json.JsonConverter {
    public override bool CanConvert(Type objectType) {
        return typeof(IHtmlString).IsAssignableFrom(objectType);
    }
    ...
    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
        IHtmlString source = value as IHtmlString;
        if (source == null) {
            return;
        }
        writer.WriteValue(source.ToString());
    }
}

Background

While working on some random API, we noticed one of our JSON fields went from being a long string containing raw HTML (legacy baggage) to an empty object: SomeFieldWithHtml: {}.

While the API JSON-generating code hadn’t changed, that field was pulled from code shared by our MVC website. It seems that field was converted directly to an IHtmlString to avoid doubly-encoding it in an MVC view. If you ever have the same issue, you can avoid this issue entirely by leaving the source as a string and doing a quick MvcHtmlString.Create(x) on it before sending it to your view/view-model.

Code

For the full source used in this post, including an example MVC project where a controller has action methods to test all the variations here, head over to this post’s GitHub repository.

Performance Stub: getting all subtype items from a list

Performance Stubs

These blog posts are simply times I wanted to identify the fastest method for accomplishing a particular goal. As I write the code, I like to make some light notes of alternatives while driving forward with the first implementation that makes it from my brain to my fingers.

When I get the chance, I can go back and flesh out the two versions and drop them into some basic Stopwatch timing to determine which is better in terms of raw speed. Factoring those results with clarity of code, I have a method I will likely choose the next time I need the same feature.

Goal

Given a particular IEnumerable, find all the elements that are of a particular type (subclass, in this case).

Method 1: Select As, Where Not Null

The as operator with convert between two types with one nice tweak. If the cast cannot happen, it results in null.

In this version, we massage the list by hitting all items with an as cast and then filter out the ones that didn’t cast successfully.

public static IEnumerable<SubSomething> SelectAsWhereNotNull(IEnumerable<Something> source) {
    return source.Select(item => item as SubSomething).Where(item => item != null);
}

Method 2: Where Is, Cast

There is also the is operator. Instead of returning a cast result, it simply returns a boolean for whether the instance can be cast as a given type. From there, we use another Linq extension method: Cast<TResult>.

In this version, we filter the original list to just those that can make the cast successfully, then Cast those items to the final desired type.

public static IEnumerable<SubSomething> WhereIsCast(IEnumerable<Something> source) {
    return source.Where(item => item is SubSomething).Cast<SubSomething>();
}

Test

I built up a list (n=1,000,000) of parent type Something but make every other item a SubSomething (which is a subclass of Something). Then, I run that list through both methods 1000 iterations each.

Results

Clarity

Neither method is particularly difficult to decipher. The Select/Where method takes a few more characters, but not enough to hurt.

Speed

It takes quite a list for these tests to even register with average ticks. That said, there is little gain to be had here over small lists. Once list lengths are sufficiently large, method 1 took the lead.

For n=1,000,000 and 1000 iterations (run on 2.4GHz AMD Phenom 9750 with 8GB RAM)
Average Method
1.0 ticks {IEnumerable<Something>}.Select(item => item as SubSomething).Where(item => item != null)
1.7 ticks {IEnumerable<Something>}.Where(item => item is SubSomething).Cast<SubSomething>()

Performance Testing Framework

The original source for the test framework code evolved from a StackOverflow answer about converting byte arrays to hexadecimal strings. –That code is available in a bitbucket repo. I have adapted it here for these two methods.– That code is available in the framework repo.

Rather than post another repo for each test, I am going to abstract out a testing framework for these posts. That repo will show up soon and I will update this post accordingly.

Update 2013-01-22

I finally refined the testing framework code I was using. While I won’t pretend this code couldn’t use some improvements, feel free to hack away with it. The code is available on GitHub.

To add a new case to an existing test:

  1. Add the new static method (Func<byte[], string>) to /Tests/ConvertByteArrayToHexString/Test.cs.
  2. Add that method’s name to the TestCandidates return value in that same class.
  3. Make sure you are running the input version you want, sentence or text, by toggling the comments in GenerateTestInput in that same class.
  4. Hit F5 and wait for the output (an HTML dump is also generated in the /bin folder).

To add a new test fixture entirely, just write up something that implements IPerformanceTest in that project’s namespace.