A technology-agnostic blog about technology.

Displaying web images with MonoTouch – UIWebImageView

By ESCOZ posted December 18th, 2009

When displaying images from the web on iPhone applications, we should always make sure the images are never be downloaded in the application thread, to avoid locking the application; we should also always display feedback to the user that the image is being loaded. There are several libraries that take care of this functionality in Objective-C, but I couldn’t find anything in C#, using MonoTouch, so I decided to create a simple one.

Here’s how it works. The new UIWebImageView control inherits from UIImageView with either C# or NIB files. For that to happen, we need a series of constructors, like below:

	[Register("UIWebImageView")]
	public class UIWebImageView : UIImageView
	{
		NSMutableData imageData;
		UIActivityIndicatorView indicatorView;

		public UIWebImageView (IntPtr handle) : base(handle)
		{
			Initialize ();
		}

		[Export("initWithCoder:")]
		public UIWebImageView (NSCoder coder) : base(coder)
		{
			Initialize ();
		}

		public UIWebImageView(RectangleF frame){
			Initialize();

			indicatorView.Frame = new RectangleF (
                        frame.Size.Width/2,
                        frame.Size.Height/2,
                        indicatorView.Frame.Size.Width,
                        indicatorView.Frame.Size.Height);
		}

		public UIWebImageView(RectangleF frame, string url):base(frame){
			DownloadImage(url);
		}
	}

The NSMutableData class simply works as a buffer of bytes, and will be used to keep the data while its being downloaded from the url. We also set the indicatorView frame, so that it shows right in the middle of the image that will be downloaded.
The Initialize() method simply sets up the indicatorView object:

		void Initialize ()
		{
			imageData = new NSMutableData();

			indicatorView = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.Gray);
			indicatorView.HidesWhenStopped = true;
			var width  = (this.Frame.Width-20)/2;
			var height = (this.Frame.Height-20)/2;
			indicatorView.Frame = new RectangleF(width, height,20,20);
			this.AddSubview(indicatorView);
		}

While the DownloadImage() method turns the indicatorView visible and starts the download:

		public void DownloadImage(string url){
			indicatorView.StartAnimating();
			NSUrlRequest request = new NSUrlRequest(new NSUrl(url));
			new NSUrlConnection(request, new ConnectionDelegate(this), true);
		}

Here we’re using two other classes from the Apple Foundation framework (MonoTouch.Foundation namespace). We could have used .NET’s classes to download the objects as well.
The ConnectionDelegate object we’re passing is an inner class, that is responsible for receiving the callbacks from the UrlConnection object when the data is being downloaded.

		class ConnectionDelegate : NSUrlConnectionDelegate {

			UIWebImageView _view;

			public ConnectionDelegate(UIWebImageView view){
				_view = view;
			}

			public override void ReceivedData (NSUrlConnection connection, NSData data)
			{
				_view.imageData.AppendData(data);
			}

			public override void FinishedLoading (NSUrlConnection connection)
			{
				System.Threading.Thread.Sleep(5000);
				_view.indicatorView.StopAnimating();
				UIImage downloadedImage = UIImage.LoadFromData(_view.imageData);
				_view.Image = downloadedImage;
			}
		}

That’s it! To instantiate it using Interface Builder, simply drag and drop a UIImageView into your view, and then change the class type to “UIWebImageView”. Don’t forget then to call the method “DownloadImage(url)” from your code to start the download.

UPDATE: The full class can be found on GitHub.. You can also download the entire solution with a sample app from here.


iPhone development with MonoTouch

By ESCOZ posted December 18th, 2009

For the last month, I’ve been playing with MonoTouch, Novell’s platform for development for the iPhone. MonoTouch runs on top of a custom build of Mono, the linux implementation of the .NET platform.

As a .NET/Java/Ruby developer, its wonderful to finally a higher level language available for the iPhone. I have spent several months during the last year playing with Apple’s SDK, in Objective-C, and I can safely say that I can be a lot more productive on MonoTouch. Not having to deal with traditional C-like language issues (memory management, pointers, etc) makes me focus a lot more on the APIs and the business logic.

Not everything is perfect unfortunately: MonoDevelop, the open source “copy” of Visual Studio, is just not as good as it could be. Novell did a very good job with integration between MonoDevelop and the Apple tools (simulator, Interface Builder, and so on), but the frequent crashes just get in the way. Hopefully new versions will address those problems.

I’ll be posting updates and more info about MonoTouch and personal and work projects I’m working on soon.