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