A technology-agnostic blog about technology.

Notes from an (officially new) iPhone developer

By ESCOZ posted February 6th, 2010

I have just finished uploading a new application to the App Store. While it’s waiting for Apple’s approval (hopefully that will happen soon), I decided to write down some information about how the application was developed. This won’t be a technical guide or a how-to; rather, these are some random thoughts that new developers to this platform can probably learn from.

Step 1 – Get the idea right

This is the first and the most important step: make sure your idea is rock solid, and that it’ll work well for the iPhone. The iPhone is an extremely constrained platform (small screen, no keyboard, no mouse, etc), so you need to make sure your application is doing the perfect thing for your user. Back in 2008, I attended an Apple Developer Day specifically for the iPhone, and the one thing I took out of that presentation were the ingredients to create a good iPhone app. You can watch that video here – Seven Qualities of Successfull iPhone Apps. Always remember that iPhone apps are not supposed to do everything, and that 90% of the ideas you’ll have won’t fit well in the Phone.

Step 2 – Go back to paper and pencil

Now its time to put write your idea down, and design how your app will look. There are some online tools available to do that, but nothing is easier and simpler than a sketch book and a pencil. I always use Erik Loehelm’s great template, and recommend everybody else to do so.

Iterate over your design multiple times. I mean, really, multiple times. Think about the position of every element, and how you could remove that element in the first place. The iPhone is very different from a normal page or desktop app, so saving space and finding innovative ways of displaying data is fundamental.

Step 3 – Do it!

Not much to say here, other than that this is hard and will take a long time to be done. Choose your tools wisely, based on what you know and what you want to learn, and just do it. Many times during development you’ll feel the urge to add new features to the app; many new features will be only a couple of lines away from you. Resist the temptation! Focus on your original wireframes, and getting that done.

Technically speaking, make sure you do things the right way: web calls should always be done asynchronously, UI elements should always be preloaded, memory should be freed as quick as possible. Get very used to write threaded code, and be extra careful with memory leaks. The iPhone is a fast computer in many ways, but you’ll often be amazed at how it is slow at some things.

Step 4 – Test it, and test it again!

Be very serious about testing. Nothing is worse than spending your users time by having your app crash every once in a while. Make sure you test special conditions: network on/off, rotating the app, different versions of the iPhone OS, multiple touches at the same time, and so on. Make sure you keep lists of all the bugs you have found. In my case, I like to use 37Signal’s Backpack application for that, but it really doesn’t matter which tool you use.

Make sure you always test in the iPhone, not on the simulator. The simulator only simulates the iPhone OS, not the hardware, and there are thousands of differences between each platform. You’ll find a lot of bugs in the phone that simply do not happen in the simulator.

Step 5 – Make it pretty

This step really should happen all along the way, but I thought it would be better to have a different topic for it. Along the way, you’ll have to develop multiple controls for your applications, buttons, align text, show different icons, decide on colors to use, and many other things.

Here’s my tip: Hire a designer.

If you can’t, do not try to do the design the app right away. Rather, try to first become a little bit of a designer. Learn about colors, learn about photoshop, learn about UI design. Apple provides lots of guidelines on UI design for the iPhone. Read it all, multiple times. Also learn about animations, and how give the user the right feedback at the right time.

UI design is hard stuff, a lot harder than most developers (me included) would like to give credit for.

Step 6 – Enjoy

Yes, you have just finished developing your new app. You have just submitted it to the App Store, and now you’re contemplating what to do. This is the step I am at right at this moment (February 6th 2010, 4pm).

Thinking back, it seems that the fact you need Apple’s approval to run your application on the iPhone is not entirely bad. It definitely forces you to focus a lot more on the steps above, which translates into a better application for your users.

It also translates to a lot more work, but nobody ever said this was going to be easy. Apple’s frameworks make it a fairly easy task to develop an iPhone app, but all the things around the platform in general end up taking a lot more work than you were probably expecting (at least that happened for me).

Overall, spending the last 3 weeks developing the new application all by myself was an amazingly gratifying experience, different from any other experience I’ve had developing for the web. Highly recommended.


MonoTouch Presentation at the ChiPhone Group

By ESCOZ posted February 5th, 2010

Later this month I’ll also be talking about MonoTouch at the chiPhone User Group. I’ll also have the pleasure of hosting the meeting this month at our offices at the Willis Tower (old Sears tower):

The presentation will be pretty much the same as the one I’ll give to the Chicago ALT.NET group, but because most people in the group already develop iPhone apps using XCode I’ll try to talk more about .NET in general and C#, instead of on the iPhone library.


ALT.NET Chicago MonoTouch Presentation

By ESCOZ posted January 28th, 2010


Next month I’ll be presenting about MonoTouch at the ALT.NET Chicago February 2010 Meeting:

MonoTouch is a new SDK based on Novell’s Mono platform that allows developers to create native iPhone (and soon iPad) applications using .NET languages and APIs. In this presentation, I’ll be talking about the iPhone platform in general, how MonoTouch fits in that ecosystem, and I’ll show how to create a quick sample application.

If you’re coming to the meeting, and have any questions or things you would like to see in the presentation, please contact me!

As many of you know, I’ve been co-hosting the ALT.NET meetings the great Sergio Pereira at our Redpoint office for the last two years, so it’s was big pleasure to be invited to present. Thanks goes to Sergio for the opportunity!


Developing with MonoTouch on Windows and Visual Studio

By ESCOZ posted January 28th, 2010

Here’s how to develop with MonoTouch on Windows and Visual Studio 2008. You won’t be able to compile the code, as it depends on libraries that simply do not exist on Windows, but tools like Resharper will work perfectly. This will allow you to write the code faster, but you’ll still need the mac to run the app on the Simulator or the iPhone.

On the mac:

  1. Create a new project with MonoTouch
  2. Put it in a network share, or a code repository, so it can be accessed from Windows.

On Windows:

  1. Download 7-zip and install
  2. Download MonoTouch’s trial version. We’ll need one DLL from this package.
  3. Open the pkg file with 7-zip and go to this directory: monotouch-eval-1.4.7.pkg\monotouch.pkg\Payload\Payload~\.\usr\lib\mono\2.1\
  4. Extract all the DLLs to a directory of your choice (not inside the project).
  5. Make copies of your SLN and CSPROJ files, and call them “mysolutionVS.sln” and “myprojectVS.csproj
  6. Edit your new mysolutionVS.sln:
    • Change the two references (at the top and bottom of the file) to point to the new myprojectVS.csproj.
  7. Edit your newmyprojectVS.csproj file:
    • Delete the “ProjectTypeGuids” line. In my case, the line to be deleted contains the following:
      <ProjectTypeGuids>{E613F3A2-FE9C-494F-B74E-F63BCB86FEA6};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
  8. Create a new file in the same directory called “myproject.csproj.user”, with the following content:
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    	<PropertyGroup>
    		<ReferencePath>C:\path\to\monotouchlibrary\</ReferencePath>
    	</PropertyGroup>
    </Project>

    The ReferencePath above should point to the directory where you saved the DLL files in step 3. Do not include the dll name.

  9. Open the new solution with Visual Studio.
  10. Finally, remove the current references in that the project contains, and add references to the DLLs from the directory in step 3.

That’s it! You’ll now be able to open the solution in Visual Studio, and use tools like Intellisense, Resharper and others to facilitate the development. To compile the app, use the original solution file in MonoTouch. If you add or remove files, make sure you add them again when you go back to MonoTouch.

While I prefer to make these changes manually, as they’re quite simple, that may not be the case for you. In that case, Manfred Pohler created a little application that automatically does it for you, called VSMTouch. I haven’t used it, but it seems to do something similar to the steps above.


MonoTouch Calendar control is here!

By ESCOZ posted January 22nd, 2010

Here’s a new MonoTouch UIView many people will probably find useful: CalendarMonthView. As you can see in the picture on the side, this control is a copy of the built in Month View calendar control, used in Apple’s calendar app. This includes animations when moving between months, highlighting of the cells being selected and current day, etc.

Even if you’re not going to use the control anytime soon, I would still recommend taking a look at the code simply an example of how to develop a control like it. This code is based on the calendar control from the great Tapku Library, created by Devin Ross, and reading over that was a great way of learning more about the UIKit.

Using this control is really simple, as you can see in the  sample CalendarMonthViewController. All you have to do is instantiate a new CalendarMonthView control, and add it as a subview to the current view:

public class CalendarMonthViewController : UIViewController
{
	public CalendarMonthView MonthView;

        public override void ViewDidLoad()
        {
            MonthView = new CalendarMonthView();

			MonthView.OnDateSelected += (date) => {
				Console.WriteLine(String.Format("Selected {0}", date.ToShortDateString()));
			};
			MonthView.OnFinishedDateSelection += (date) => {
				Console.WriteLine(String.Format("Finished selecting {0}", date.ToShortDateString()));
			};
			MonthView.IsDayMarkedDelegate += (date) => {
				return (date.Day % 2==0) ? true : false;
			};

            View.AddSubview(MonthView);
        }
}

During the next few days, I’ll be adding a few new features to the control, like Range selection, more events, etc. The code still have a few small rendering bugs, which I’m working on. If there’s anything you would like to see implemented, let me know!

The full source code can be downloaded from my samples library in GitHub.

Update: I just committed a couple of changes to the control, one of them being the new delegate IsDateMarkedDelegate, which is used to display a mark for a day in the grid. To use this, simply create a new delegate or lambda expression (as above), and return true to display the mark. This to me seems considerably easier to implement then passing a list of DateTime objects that should have the dates, which is how this is implemented in the Tapku control.


TapkuLibrary’s LoadingHUDView control ported to MonoTouch

By ESCOZ posted January 19th, 2010

I have just pushed to github a port of the great TapkuLibrary’s LoadingHUDVIew control to MonoTouch. You can find the C# LoadingHUDView implementation here, or just download the entire solution to see the control working.

The code was translated mostly line-by-line, so the two classes still look very much alike. For comparison, the Obj-C code has around 130 LOC, plus another 10 for the Interface and around 20 of extension methods being used. The C# code has 140 in total. Not much of a difference, really. There’s quite a few things in the code that could be refactored, though, so the line count can probably be a bit lower than that.

To use the control, simply create a new object in code, and add it to the View, like below:

var hud = new LoadingHUDView("Loading", "This is the long message");
View.AddSubview(hud);
hud.StartAnimating();
NSTimer.CreateScheduledTimer(TimeSpan.FromSeconds(5),
                 ()=>hud.StopAnimating());

The code above will display a popup, and close it after 5 seconds. In the real world, you’ll likely call the StopAnimating() method after a web service returns, or a calculation completes, for example. Take a look at this Controller class for a better example of how to use the control.

MonoTouch makes it possible to load Objective-C compiled libraries to the compilation of the project, but C# bindings still need to be created to access those classes during runtime. The MonoTouch API documentation is fairly helpful; the only problem is it mentions a Binding Generator, but there’s no documentation for it in the wiki yet. Anyway, the major problem for me with that approach is that in order to make changes to the control, you have to fire XCode again, recompile, and then recompile in MonoDevelop. After doing that a few times, I just decided that translating the code was easier.

My thanks goes to Devin Ross, creator of the open source Tapku Library, for the great work! I’ll likely be rewriting some of the other controls as well, like the Calendar view.


Editing Decimal Numbers with UITextField control with MonoTouch

By ESCOZ posted January 16th, 2010

Here’s another control I created while developing an iphone app for a client: UIDecimalField. The entire source code can be found on github, together with the other controls I have created so far. You can see the control in use in the image on the right.

The new control inherits from the UITextField control, and allows the user to edit decimal values using the NumberPad keyboard, instead of the normal keyboard. Again, as I mentioned in my previous post, inheritance provides a much better way of adding functionality to existing UIKit controls, instead of doing composition.

First, we need to change the Keyboard type used by the control. That is as simple as changing the property during the initialization of the control:

public partial class UIDecimalField : UITextField
{
	public decimal Value {
		get { return UIDecimalField.GetAmountFromString(Text); }
		set { Text = value.ToString("N2"); }
	}

	public UIDecimalField (IntPtr ptr) : base(ptr) {
		Initialize();
	}

	protected void Initialize() {
		KeyboardType = UIKeyboardType.NumberPad;
		Delegate = new UIDecimalFieldDelegate();
	}
}

Now we need to handle the user input and transform the text in the control, so that numbers are always formatted as a decimals, including rounding and decimal/thousand separators. That is done by creating a new class that inherits from UITextFieldDelegate, and overriding the ShouldChangeCharacters() method, as below:

public partial class UIDecimalField : UITextField
{
	public decimal Value {
		get { return UIDecimalField.GetAmountFromString(Text); }
		set { Text = value.ToString("N2"); }
	}

	public UIDecimalField (Decimal currentValue): base() {
		Value = currentValue;
		Initialize();
	}

	public UIDecimalField (IntPtr ptr) : base(ptr) {
		Initialize();
	}

	protected void Initialize() {
		KeyboardType = UIKeyboardType.NumberPad;
		Delegate = new UIDecimalFieldDelegate();
	}

	private class UIDecimalFieldDelegate : UITextFieldDelegate {
		public override bool ShouldChangeCharacters (UITextField textField,
			NSRange range, string replacementString) {

			var newText = textField.Text.Remove(range.Location, range.Length)
							.Insert(range.Location, replacementString);

			if (newText.Length>0){
				textField.Text = (UIDecimalField.GetAmountFromString(newText)).ToString("N2");
			}
			return false;
		}
	}
}

Overriding this method means that we’ll have to rewrite the way a normal UITextField handles user input. That is done using the Insert()/Remove() methods in the first line. With the new text, we’ll have to convert the value to a decimal and reformat it, which is done by the static method listed below. Finally, we return false to prevent the base class from handling the user input.

Here’s the static method to convert the text:

private static decimal GetAmountFromString(string text){
	if (text.Length==0)
		return 0;

	var cleanedUpText = "";
	foreach (char c in text)
		if (Char.IsDigit(c)) cleanedUpText+=c;

	return (decimal.Parse(cleanedUpText))/100;
}

The code above rounds the decimals to 2 decimal places; modifying the code for different rounding should be just a matter of adding an additional property in the class and modifying the last row of the method above and the ToString(“N2″) above.


Monotouch tip: Inherit UIViews ALL the time!

By ESCOZ posted January 13th, 2010

When I started developing with MonoTouch, I ended up reading lots of tutorials, and watching lots of YouTube screencasts.

While those were definitely useful to get started on the platform, the large majority of them seem to implement things in a way that simply doesn’t scale very well: by adding outlets of every control to the AppDelegate class or to a ViewController, in Interface Builder. While that may work right in a simple HelloWorld app, it simply doesn’t scale well. It’ll become impossible to manage the application after you add more than a couple of views and controls.

Inheriting from UIView (or UIScrollView), is a much better way of creating views for your application. Interface Builder can still be used to design the UI, while the coding of the behavior can be done in MonoDevelop. Doing this will make the code much cleaner, by allowing you to separate different concerns across different classe: ui-related functions, like formatting of the text or the selection of the background color can be done in the View class, while definition of what’s loaded, and calling web services can be done in the Controller.

To do this, first go to Interface Builder, and build your UIView with some labels as normal. Now, go to the Library, select “Classes” from the top selector, and find the UIView class. Right click on it, and select “Add subclass”. Type in the name of your new view, like UserView, and click ok. Finally, select the view you created previously, go to the Object Identity field, and change the class to the new subclass.

After you save the Interface Builder file, MonoTouch will automatically generate a partial class for your new view, like below:

// Base type probably should be MonoTouch.UIKit.UIView or subclass
[MonoTouch.Foundation.Register("UserView")]
public partial class UserView{
}

By itself, that is not very useful. But the difference is that now you can create outlets to the UILabels in this new view, instead of in the controller! Doing that would generate code like this:

// Base type probably should be MonoTouch.UIKit.UIView or subclass
[MonoTouch.Foundation.Register("UserView")]
public partial class UserView{
	[MonoTouch.Foundation.Connect("Key")]
	private MonoTouch.UIKit.UILabel NameLabel {
		get {
			return ((MonoTouch.UIKit.UILabel)(this.GetNativeField("NameLabel")));
		}
		set {
			this.SetNativeField("NameLabel", value);
		}
	}
}

Notice how the property created is defined as private. It’s great that MonoTouch defaults to private, as it forces you to define a public method for the view, which will likely have more to do with the application domain, instead of just calling the labels from the controller.

Finally, you’ll need to create the other side of the partial, with the real implementation of the class, and constructors. For that, create a new file in MonoDevelop called UserView.cs, like below:

public partial class UserView : UIView {

	public UserView (IntPtr p) : base (p) {
	}

	public void DisplayUser(User user) {
 		NameLabel.Text = user.Name;
	}
}

You’ll need to inherit your class from UIView, like you defined in Interface Builder, and implement a default constructor that receives an IntPtr object, passing that directly to the UIView’s constructor. This constructor is used by MonoTouch to instantiate the object when it’s deserializing the view from the NIB file. I also included a simple method called “DisplayUser()”, just to give a rough idea on what you can do here. Your views will probably have much more complicated logic here.

Lastly, your views will receive events from the User, and you’ll need to pass that to your controllers. Personally, I prefer to user Interface Builder to create events directly in the controller, and just hookup the events directly. The controller in C# would then implement that event, and be responsible for getting the data from the view. For complicated views, it might be useful to also create the event directly in the view class.

That’s it! The view code is now totally separate from the AppDelegate or any controllers. While this seems overkill for such a simple example, for larger applications this will enormously increase the quality of your code.


Displaying different views when iPhone is rotated with MonoTouch

By ESCOZ posted January 7th, 2010

Here’s another control I developed while working on an iPhone application using MonoTouch.

Its very common for games to make use of the accelerometer inside the iPhone, but not so much for data-driven apps. One app that uses it very well is WeightBot, from TapBots, which display charts with different views of the data when you rotate the phone to the left or the right. I wanted to do the same for my application, and ended up writing another ViewController.

View controllers always need at least one UIView objects to display: the UIViewController has one, while the NavigationViewController has a list of many. In our case, the RotatingViewController will have three: one for portrait view, and two for landscape views:

[Register("RotatingViewController")]
public class RotatingViewController : UIViewController
{
	public RotatingViewController (IntPtr handle) : base(handle)  {}

	[Export("initWithCoder:")]
	public RotatingViewController (NSCoder coder) : base(coder) {}

	public RotatingViewController (string nibName, NSBundle bundle)
		 : base(nibName, bundle) 	{}

	public RotatingViewController () {}

	public UIViewController LandscapeLeftViewController {get;set;}
	public UIViewController LandscapeRightViewController {get;set;}
	public UIViewController PortraitViewController {get;set;}
 }

I use here links to the UIViewController of the views, instead of directly to the view, because those views need to be set to allow rotation.

Now that we have the views, we need to register with the OS to receive notifications when the iPhone is rotated. For that, we will use NSNotificationCenter and the UIDevice.CurrentDevice object:

 public override void ViewDidLoad()
{
	notificationObserver  = NSNotificationCenter.DefaultCenter.AddObserver("UIDeviceOrientationDidChangeNotification", DeviceRotated );
}

 public override void ViewDidAppear (bool animated)
{
	UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications();
}

public override void ViewWillDisappear (bool animated)
{
	UIDevice.CurrentDevice.EndGeneratingDeviceOrientationNotifications();
}

private void DeviceRotated(NSNotification notification){
       // change the views on demand
}
 

We are registering the new observer “DeviceRotated” in the ViewDidLoad method because we want to make sure it is just created once, while we use the ViewDidAppear and ViewWillDisappear to only cause notifications when this view is visible. The deviceRotated method finally swaps the views accordingly to the mode of the view.

The entire source code can be found on GitHub. The class currently doesn’t handle special animations to transition between the views, which is something I’ll tackle later on. If your views are very complicated or use lots of memory, this can be a problem, as the views are not being created on demand.

Make sure you download the entire solution, which contains a sample application using the control.


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.