Simon says, why we chose MonoTouch to write the Diggify iPhone app

Written by Simon Guindon. Posted in Coding, Diggify, Featured, Mobile, MonoTouch

There has been lots of talk about the new restrictions in the latest developer agreement on the AppStore that came about when iPhoneOS 4 was announced. It has been a hotly debated topic to say the least. The new legal text in section 3.3.1 is essentially trying to lock in what languages and tools developers use to build their iPhone, iPod Touch and iPad applications.

I’m not going to rehash the same Apple vs Adobe banter that has been going on. It’s been talked about to death. What I am going to talk about is what I believe in as a developer, and why MonoTouch was chosen to build Diggify.

There has been much confusion among various blogs and publications regarding what MonoTouch is and how it works. This stems from the root of what MonoTouch is, which is a .NET and C# offering for iPhone. When people read .NET they jump to conclusions by associating MonoTouch with Microsoft’s user interface libraries such as Windows Forms or Silverlight. This steers people into believing MonoTouch is a non-native UI toolkit ala Flash or various others. Let me clarify before I jump to the experiences and comments.

What MonoTouch is not:

  • Non-native UI toolkit
  • Cross-platform UI toolkit
  • JIT and Intermediate Language runtime

What MonoTouch is:

  • Native Cocoa Touch UI
  • Native ARM compilation
  • Bindings to iPhone SDK libraries that you can use in C#
  • .NET class library
  • Ability to wrap any native API in C#
  • Fast
  • Garbage Collected to simplify memory management
  • Debugging over WiFi (Xcode cannot do this)
  • Very quick to support new API’s from Apple’s iPhone SDK (usually within 24 hours)
  • Fully supported by Novell
  • Direct access to Novell software engineers via chat rooms, forums etc
  • Vibrant and friendly community

I started with MonoTouch during the closed beta program from the very beginning and can’t say enough good things about the MonoTouch team at Novell. During that time, I decided to write a Digg client app for release on the AppStore. At the time this beta program began I had nearly a year of Objective-C development under my belt. This was not a case of “I will only write iPhone applications if my favorite language somehow gets on the iPhone“. Although C# is the main language I have used through my career, I have many others and am not a 1 trick pony. If MonoTouch did not exist, I would be writing Objective-C based applications.

The app built is called Diggify and is available on the AppStore today which can be found here on iTunes and also has a website describing the application which you can find at http://www.diggifyapp.com.

The goals in Diggify were to make a rich Digg application that had great user experience and visuals as well as good usability for navigating the application while at the same time making it as speedy as possible. All of these goals were achieved.

The reasoning for going with the MonoTouch SDK cover several reasons. As mentioned earlier, C# is the language I know the most which means any previously written non-UI code I have in C# I can leverage on the iPhone. This is huge because if I wish to write Diggify for Windows Mobile (at the time) or Windows Phone 7, I can carry over large chunks of my code but leverage the native UI API’s of both iPhone and Windows Phone 7. Remember from above, MonoTouch is not a cross-platform UI toolkit.

To clarify, this means I can write the core meat of my applications logic, data, REST requests for multiple platforms, while leveraging the powerful native UI on the local device. On iPhone this would compile down to Cocoa Touch API calls in native ARM and on Windows Phone 7, Silveright.

In addition to this, MonoTouch is essentially giving me the iPhone SDK+.NET framework. I am getting both. I can use Apple API’s for things like Core Animation to make my transitions and visuals pop, and use System.Xml, System.Xml.Serialization and System.IO from the .NET framework to parse XML and persist them to the file system. I have 2 SDK’s at my arsenal, while not sacrificing the UI. This is key because Apple does not provide things like XML libraries, or WCF/SOAP libraries. I can lean on the .NET API’s to quickly and easily offer these functionalities to me.

MonoTouch comes with MonoDevelop a first rate developer IDE which integrates very smoothly with Apple’s Interface Builder to build your UI’s with. I believe MonoDevelop integrates more seamlessly with IB than Xcode does from Apple. The MonoTouch team has done a great job at trying to make the productivity of building iPhone applications as good as possible.

When writing Objective-C based applications with the iPhone SDK you do not have the garbage collector that Apple provides on the Mac. This and various API’s missing makes developing iPhone applications more time consuming and error prone. Managing memory is a more difficult task and can cause hard crashes in your application. As you grow in experience you get better at these things, but I found using Objective-C I was spending more time on plumbing than on the application’s features, visuals and user experience.

With MonoTouch I was able to really spend a lot of time fine tuning UI and performance. Rich iPhone applications can tend to be a little sluggish if not done right. Like on any mobile device, squeezing performance is skill. You do not have 2ghz dual cores on these phones. This is why apps like Tweetie do so well. Their using rich visuals while blazing fast. I was able to do the same with Diggify by having a rich dynamic user interface while maintaining fast scrollable lists that looked great.

To say this simply: I was able to focus on building a great application rather than spending all my time on low-level book keeping.

When Diggify launched on the AppStore Digg had already released their Digg application a week or so previous, and for free. I had planned and did price Diggify at 99c. In reality Digg’s free app hurts our chances because it was free and obviously it is their own app and they have the platform to market it on their own website to millions of users.

Even though the Diggify application is richer in visuals and user experience (in my opinion and several others from feedback given), one interesting thing happened on the official Digg app launch. The app was rampant with bugs. The AppStore reviews were terrible and the complaints of the app crashing constantly were the common theme. Twitter was also full of comments about how crashtastic the application was. I was able to boost my sales by simply tweeting to people encountering this difficulty (and there were many of them) and making them aware that Diggify existed. Since our marketing is very small and awareness was the largest issue, this helped a great deal.

Using this tactic we had reached as high as 8th in the top paid news category.

In addition to this, all of the feedback we were receiving was all about adding X, Y feature. Not one comment was about a crash or performance issues. The users simply wanted more. One tweet was as follows:

benny_b0i
Got @diggify and like what I see. Transition FX and upcoming are cool, and it’s fast! Would like to be able to digg and see comments tho.

4:53 AM Apr 6th via Twitbit for iPhone in reply to diggify

After initial launch we were able to quickly add some UI tweaks and small features right away based on other user feedback received.

Steve Jobs recently posted an article clarifying his opinions and stance on the topic and although I do agree with parts of what he is saying, there are a couple statements I disagree on. Steve on his article states the following:

“We know from painful experience that letting a third party layer of software come between the platform and the developer ultimately results in sub-standard apps and hinders the enhancement and progress of the platform. If developers grow dependent on third party development libraries and tools, they can only take advantage of platform enhancements if and when the third party chooses to adopt the new features. We cannot be at the mercy of a third party deciding if and when they will make our enhancements available to our developers.”

MonoTouch is a 3rd party SDK however Diggify vs Digg’s official app is a no contest regarding which is the more stable application. Much of this is credited to MonoTouch’s garbage collector, type safety, etc.

Steve goes on to add:

“Again, we cannot accept an outcome where developers are blocked from using our innovations and enhancements because they are not available on our competitor’s platforms”

MonoTouch adds new API’s when Apple releases them within 24 hours. If I didn’t like Novell’s quality in their SDK or support I have the choice to go elsewhere or back to Objective-C.

The initial release of the official Digg app’s main issue was a start-up crash. How that got past QA I don’t know. From there most updates have been fixing various crashes and issues.

We submitted the first app update mostly based on user feedback of UI tweaks they requested 2 days after the initial AppStore approval. Let’s compare the Digg/Diggify updates:

Digg Update

diggify-update-01

Based on the experience, the quoted statements above from Steve are not the case and is actually the opposite. We are receiving inherited benefits from using a 3rd party SDK which also builds on top of the iPhone SDK. MonoTouch is adding value to the iPhone SDK, not an alternative.

My opinion comes down to this. Bad developers write bad applications. The official Digg application was a bad application to release at the time. It was bug filled. They have refined it over time, but during that time I had 0 complaints, and was moving forward. Since MonoTouch uses the native iPhone API’s and compiles to native ARM, there is no risk in Apple allowing us to write applications in C# via MonoTouch.

Languages and compilers are tools. Do I not get to choose which hammer I wish to use when hitting a nail? In the end as long as we are using documented API’s (which MonoTouch is) and native UI, Diggify is no different than any other iPhone application. Not even 1 user has said that the application feels different. No cycles were spent on making it feel like a native iPhone application simply because, that is what it is. Diggify is calling the same API’s. No extra work is needed. The source language that the application is written in has nothing to do with the look and feel or usability of an application.

By no means is this a post against Objective-C. I simply feel the diversity which is the development world should be embraced not suffocated. MonoTouch was chosen for Diggify for the reasons above. Perhaps you have reasons for using Objective-C or any other language, I believe that it should be our choice.

Perhaps the team writing the official Digg app had unrealistic time constraints and this was the end result. Regardless, from our experience MonoTouch gave us a product that allowed us to focus on the app, preventing us from repeatedly shooting ourselves in the foot all while our time to dedicate to the project was limited.

I feel if Apple truly wants to go the proper route to filter out crappy apps, the path is through QA, not by banning the source language the app was written in.

Apple, let’s work together as a community to rise the level of quality on applications in an effective way that retains the freedom of choice and creativity that developers love rather than lock handcuffs on our wrists.

Update:

As pointed out in the comments below from @redth, I forgot to mention MonoTouch has a btouch tool. btouch allows us as the developer to wrap any native API ourselves in C#. If we need something Novell does not yet provide or binding to an external Objective-C library we can do so. This is an important fact to remember.

Simon says, Diggify MonoTouch app is coming soon to the AppStore

Written by Simon Guindon. Posted in Diggify, Mobile, MonoTouch, Project-D

Last week I unveiled Project-D as its real name, Diggify. We unveiled the website www.diggifyapp.com as well as the Twitter account @diggify

Submitting to Apple will be very soon. Awaiting feedback from the test team whether any minor issues have been discovered.

It’s been awhile since I blogged. A job switch certainly has made things chaotic.

I also haven’t found as many “sexy” topics to blog about as I did early on in the development of Diggify.

So I ask the people reading my blog, is there anything you see in Diggify that you want to know how I did it? If not I have some ideas of some minor things I can talk about but if there is something people want to hear about, feel free to send feedback.

Looking forward to the release. It will be a good learning experience.

Simon says, visualizing MonoTouch iPhone app graphics performance

Written by Simon Guindon. Posted in Coding, Diggify, Mobile, MonoTouch, Project-D

project-d-03

I have been debugging UITableView rendering performance when scrolling in Project-D because I feel it is a bit sub par.

Project-D uses a custom UITableViewCell designed in IB with the exact same method I talk about in my howto blog post you can find here: http://simon.nureality.ca/?p=91

I have used a lot of transparent images, and the upcoming Ticker at the bottom of the application may also be causing additional alpha blending.

I believe the performance has something to do with the amount of alpha blended layers I have added in my UI.

I have not yet found the solution but I did find a nifty way on the device and simulator to make the display visualize the alpha blended layers in shades of green/red.

Green is good, red is bad. The more red, the more alpha blending is occurring in that region. Alpha blending is very expensive on the iPhone.

As you can see, most of Project-D is red and in some areas a deep red which I suspect means alpha layers on top of alpha layers. I did heavily use transparent png’s and perhaps went a bit too much and am curious how this has affected iPhone 3G users since I own an iPhone 3GS and I am just now just barely noticing a bit of what feels like frame rate impact.

You can do this on device or simulator however I like the simulator method the best because once launched, you can continue development in MonoDevelop, where as with Instruments on device you have to run it in Xcode and attach separately in Instruments.

Here’s how to launch the simulator with visible alpha blended layers enabled:

1. Open a new file in TextEdit
2. Click Format -> Make Plain Text
3. Enter the following in the document

#!/bin/bash
CA_COLOR_OPAQUE=1 /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone\ Simulator.app/Contents/MacOS/iPhone\ Simulator

4. Save as Simulator.sh on the desktop.
5. Start Terminal and chmod +x Simulator.sh
6. Double click Simulator.sh on the desktop and the iPhone Simulator should run with layers showing up in shades of red and green.
7. Run your application or start it via the brand new MonoTouch/MonoDeveloper debugger.
8. Play with your app ui and watch the invalidated regions.

Enjoy! As always feel free to retweet the post and you can always find me on twitter via @simongui

Simon says, MonoTouch downloading images like AppStore app in less than 50 lines with CoreAnimation Transitions!

Written by Simon Guindon. Posted in Coding, Diggify, Mobile, MonoTouch, Project-D

Project-D-02_thumb

In Project-D I needed to dynamically load images in the same manner the Apple AppStore loads the application icons over the web and have them nicely render into place when the download is completed. Obviously this can’t occur in the UITableView methods because scrolling performance would be degraded significantly waiting for even 1 image to download.

I was amazingly surprised how simple this is in MonoTouch using ThreadPool.QueueUserWorkItem() and some Objective-C classes MonoTouch has wrapped bindings for. I did this all in 50 lines of code. I could have optimized it more to shrink it, but it’s 50 lines with broken out methods and Core Animation transitions. Very small and easy to do!

This is based on my blog about how to build custom UITableViewCell’s in Interface Builder which you can find here.

Inside the GetCell() method of my UITableViewDelegate I call GetImage() passing the UITableViewCell controller and the story (which contains the image uri). GetImage() queues a task with the ThreadPool to go fetch us the image so that the UITableView scrolling is unaffected.

The great thing about GetCell() on the iPhone is, it only gets called for cells which are being rendered. So we do not have to handle all the logic about calculating what is visible, what do we fetch etc. We already know what we need to download! I fade the images alpha so that they appear to fade in nicely once the download is complete.

Play Video

[code]
public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
// ... Do your usual stuff...
GetImage(controller, story);
}

private void GetImage(StoryCellController controller, Story story)
{
controller.ImageThumbnail.Alpha = 0.0f;
if (story.Thumbnail != null && story.Thumbnail.Src != string.Empty)
{
if (images.ContainsKey(story.Thumbnail.Src) == true)
{
UIImage imageThumbnail = images[story.Thumbnail.Src];
controller.ImageThumbnail.Image = imageThumbnail;
controller.ImageThumbnail.Alpha = 1.0f;
}
else
{
controller.ImageUri = story.Thumbnail.Src;
ThreadPool.QueueUserWorkItem(RequestImage, controller);
}
}
}

private void RequestImage(object state)
{
StoryCellController controller = state as StoryCellController;
if (controller != null)
{
NSUrl imageUrl = NSUrl.FromString(controller.ImageUri);
NSData imageData = NSData.FromUrl(imageUrl);
controller.ImageThumbnail.Image = UIImage.LoadFromData(imageData);

images.Add(controller.ImageUri, controller.ImageThumbnail.Image);

InvokeOnMainThread(delegate { RefreshImage(controller); });
}
}

private void RefreshImage(StoryCellController controller)
{
UIView.BeginAnimations("imageThumbnailTransitionIn");
UIView.SetAnimationDuration(0.5f);
controller.ImageThumbnail.Alpha = 1.0f;
UIView.CommitAnimations();
}
[/code]

Simon say’s Project-D UITableViewCells autosize based on text height in MonoTouch. Here’s how!

Written by Simon Guindon. Posted in Coding, Diggify, Mobile, MonoTouch, Project-D

Project-DWhile building the main story view in Project-D which uses a UITableView I needed to have each cell dynamically snap in their height based on the height of the content, which in this case is text.

To do this you must implement UITableViewDelegate along with UITableViewDataSource.

When implementing UITableViewDelegate the key override is GetHeightForRow(). This method lets us return what the height is for a particular row.

I’m doing 2 key things for performance reasons in GetHeightForRow() which are:

  1. Caching a font instance which represents the font I am using on the UITableViewCell
  2. Caching the cell height in my model, so that I only ever do this calculation once for a particular UITableViewCell

Basically what I am doing here is giving the measuring API a constraint width wise, and it will give me back a size of how high the text with this particular font consumes:

[code]
public class StoryViewTableController : UITableViewDelegate
{
private static UIFont font = null;
private StoryViewController viewController = null;

public StoryViewTableController(StoryViewController viewController)
{
this.viewController = viewController;
if (font == null)
font = UIFont.FromName("Helvetica", 14.0f);
}

public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
Story story = viewController.DataSource.Stories.Stories[indexPath.Row];

if (story.CellSize.Height == 0)
{
story.Title = story.Title.Trim();
story.Description = story.Description.Trim();

story.TitleSize = tableView.StringSize(story.Title, font, new SizeF(237.0f, 1000.0f), UILineBreakMode.WordWrap);
story.DescriptionSize = tableView.StringSize(story.Description, font, new SizeF(237.0f, 1000.0f), UILineBreakMode.WordWrap);

SizeF sizeTotal = new SizeF(237.0f, story.TitleSize.Height + story.DescriptionSize.Height + 20);
story.CellSize = sizeTotal;

if (story.CellSize.Height < 108)
story.CellSize = new SizeF(story.CellSize.Width, 108);
}

return story.CellSize.Height;
}
}
[/code]

In my UITableViewDataSource I am doing the same technique I showed in the tutorial
Let’s Build A Custom UITableViewCell and applying the new sizes that I store in the model to the cell itself.

[code]
public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
UITableViewCell cell = null;
StoryCellController controller = null;

cell = tableView.DequeueReusableCell("StoryCell");
if (cell == null)
{
controller = new StoryCellController();
NSBundle.MainBundle.LoadNib("StoryCellController", controller, null);
cell = controller.Cell;

cell.Tag = Environment.TickCount;
cellControllers.Add(cell.Tag, controller);
}
else
{
controller = cellControllers[cell.Tag];
}

Story story = stories.Stories[indexPath.Row];
controller.Title = story.Title.Trim();
controller.Description = story.Description.Trim();

// Sizing the cell.
RectangleF rectCell = cell.Frame;
rectCell.Height = story.CellSize.Height;
cell.Frame = rectCell;

// Sizing the background image.
RectangleF rectImageBackground = controller.ImageBackground.Frame;
rectImageBackground.Height = story.CellSize.Height;
controller.ImageBackground.Frame = rectImageBackground;

// Sizing the LabelTitle.
controller.LabelTitle.Frame = new RectangleF(
new PointF(
controller.LabelTitle.Frame.X,
controller.LabelTitle.Frame.Y),
story.TitleSize);

// Sizing the LabelDescription.
controller.LabelDescription.Frame = new RectangleF(
new PointF(
controller.LabelDescription.Frame.X,
story.TitleSize.Height + 10),
story.DescriptionSize);

return cell;
}
[/code]

Hopefully this helps people out. As always you can find me on Twitter via @simongui and I appreciate any retweets!

Simon say’s Project-D ticker CoreAnimation howto with MonoTouch

Written by Simon Guindon. Posted in Coding, Diggify, Mobile, MonoTouch, Project-D

project-d-01_thumb

I’ve been tweeting about Project-D for awhile now, but this will be my first blog post speaking about it. I’m sure you will catch on about what Project-D actually is but the real name is going to remain secret for a little longer.

I want Project-D to be a community driven application. I want to hear people’s feedback and put the features people really want. I also want to take the opportunity of building the application and advocating the use of MonoTouch through howtos. So in a series of blog posts as I build Project-D, I hope to show the source code of items I built and how I built them in MonoTouch.

This week I got an interesting idea from someone on Twitter who said I should have a ticker similar to CNN. I started thinking about it throughout the week and then it came to me. Some very subtle CoreAnimation effects could really make the ticker bling out at the same time not being too over the top. I also couldn’t remember if anyone did any CoreAnimation based howto for MonoTouch yet. So I decided this was a good opportunity to accomplish a couple things at once.

Here’s what I ended up with so far. Keep your eye on the bottom of the screen, so you can see the transition of the ticker. Also every 10 seconds it refreshes, so keep watching the ticker.

[youtube]7AhcwKwcglc[/youtube]

I have 2 view controllers. One for the story listing and one seperate for the ticker itself. I add it to the story view controller via:

[code]
StoryTickerController tickerController = new StoryTickerController();
this.View.AddSubview(tickerController.View);
[/code]

As you probably noticed I had the ticker slide up on load with a nice animation. I used MonoTouch’s CoreAnimation API bindings to achieve this:

[code]
void AnimateShowTicker()
{
UIView.BeginAnimations("tickerShowIn");
UIView.SetAnimationDuration(1.0f);
RectangleF rect = this.View.Frame;
rect.Location = new PointF(rect.Left, 0);
this.View.Frame = rect;
UIView.CommitAnimations();
}
[/code]

The nice thing about CoreAnimation is any properties you change after calling BeginAnimations() start to be recorded for the animation. Once you call CommitAnimations() the changes will occur. It’s a really nice way to do animations by just coding your property changes as normal. I really like how this is done.

After I got that completed for the nice on load transition, I wanted to also transition when the upcoming story changes. I decided a nice fade out to fade in would be nice. I did it as follows:

[code]
void UpdateTicker()
{
UIView.BeginAnimations("tickerTransitionOut");
UIView.SetAnimationDelegate(this);
UIView.SetAnimationDidStopSelector(new Selector("fadeOutDidFinish"));
UIView.SetAnimationDuration(0.5f);
labelTicker.Alpha = 0.0f;
UIView.CommitAnimations();
}

[Export("fadeOutDidFinish")]
public void FadeOutDidFinish()
{
labelTicker.Text = story.Title;

UIView.BeginAnimations("tickerTransitionIn");
UIView.SetAnimationDuration(0.5f);
labelTicker.Alpha = 1.0f;
UIView.CommitAnimations();
}
[/code]

Once the fade-out animation completes, I want to swap the text, and fade the label back into view.

Line 5 we tell which selector we wish to be called when the animation is finished. We declare using the [Export] attribute which method is going to be associated with a selector name so that when the animation is completed, that method gets executed. From here I do another animation but this time set the alpha to 1.0 so that the label is again visible with the new text.

And that’s all that was needed to make both effects. All very simple, subtle but slick using MonoTouch.

You can catch me on Twitter for more information and much more via @simongui. Please retweet!

Startups