Linking and voting

What if blogging and linking were more significant than voting?

Posted in Politics | Tagged , , | Leave a comment

UIKit Dynamics Tutorial with Xamarin.iOS

This article was adapted from UIKit Dynamics Tutorial, Colin Eberhardt, by permission of the publisher, Ray Wenderlich. Please visit the Ray Wenderlich Tutorials site for this and many other fine tutorials.

The vast majority of the text of this article is from the original article. Rather than setting the original material in block quotes or double quotes, we’ve chosen instead to highlight the Xamarin.iOS-specific material by setting it in bold.

Note from Ray: This is an abbreviated version of a chapter from iOS 7 by Tutorials that we (raywenderlich.com) are releasing as part of the iOS 7 Feast. We hope you enjoy!

You have probably come to realize that iOS 7 is something of a paradox; while you’re being encouraged to do away with real-world metaphors and skeuomorphism, Apple encourages you at the same time to create user interfaces that feel real.

What does this mean in practice? The design goals of iOS 7 encourage you to create digital interfaces that react to touch, gestures, and changes in orientation as if they were physical objects far beyond a simple collection of pixels. The end result gives the user a deeper connection with the interface than is possible through skin-deep skeuomorphism.

This sounds like a daunting task, as it is much easier to make a digital interface look real, than it is to make it feel real. However, you have some nifty new tools on your side: UIKit Dynamics and Motion Effects.

  • UIKit Dynamics is a full physics engine integrated into UIKit. It allows you to create interfaces that feel real by adding behaviors such as gravity, attachments (springs) and forces. You define the physical traits that you would like your interface elements to adopt, and the dynamics engine takes care of the rest.
  • Motion Effects allows you to create cool parallax effects like you see when you tilt the iOS 7 home screen. Basically you can harness the data supplied by the phone’s accelerometer in order to create interfaces that react to changes in phone orientation.

When used together, motion and dynamics form a powerhouse of user experience tools that make your digital interfaces come to life. Your users will connect with your app at a deeper level by seeing it respond to their actions in a natural, dynamic way.

Getting started

UIKit dynamics can be a lot of fun; the best way to start learning about them is to jump in feet-first with some small examples.

Open Xcode Xamarin Studio, select File / New / Project … File / New / Solution … then select iOS\Application\Single View Application C#\iOS\iPhone\Single View Application and name your project DynamicsPlayground. Change the Location if desired. Once the project solution has been created, open ViewController.m DynamicsPlaygroundViewController.cs and add the following code to the end of viewDidLoad:

UIView square = new UIView (new RectangleF (100, 100, 100, 100));
square.BackgroundColor = UIColor.Gray;
this.View.AddSubview (square);

The above code simply adds a square UIView to the interface.

Build and run your app, and you’ll see a lonely square sitting on your screen, as shown below:

LonelySquare

If you’re running your app on a physical device, try tilting your phone, turning it upside-down, or even shaking it. What happens? Nothing? That’s right—everything is working as designed. When you add a view to your interface you expect it to remain firmly stuck in place as defined by its frame—until you add some dynamic realism to your interface!

Adding gravity

Still working in ViewController.m DynamicsPlaygroundViewController.cs, add the following instance variables:

UIDynamicAnimator animator;
UIGravityBehavior gravity;

Add the following to the end of viewDidLoad:

animator = new UIDynamicAnimator (this.View);
gravity = new UIGravityBehavior (new [] { square });
animator.AddBehavior(gravity);

I’ll explain this in a moment. For now, build and run your application. You should see your square slowly start to accelerate in a downward motion until it drops off the bottom of the screen, as so:

FallingSquare

In the code you just added, there are a couple of dynamics classes at play here:

  • UIDynamicAnimator is the UIKit physics engine. This class keeps track of the various behaviors that you add to the engine, such as gravity, and provides the overall context. When you create an instance of an animator, you pass in a reference view that the animator uses to define its coordinate system.
  • UIGravityBehavior models the behavior of gravity and exerts forces on one or more items, allowing you to model physical interactions. When you create an instance of a behavior, you associate it with a set of items—typically views. This way you can select which items are influenced by the behavior, in this case which items the gravitational forces affect.

Most behaviors have a number of configuration properties; for example, the gravity behavior allows you to change its angle and magnitude. Try modifying these properties to make your objects fall up, sideways, or diagonally with varying rates of acceleration.

NOTE: A quick word on units: in the physical world, gravity (g) is expressed in meters per second squared and is approximately equal to 9.8 m/s2. Using Newton’s second law, you can compute how far an object will fall under gravity’s influence with the following formula:

distance = 0.5 × g × time2

In UIKit Dynamics, the formula is the same but the units are different. Rather than meters, you work with units of thousands of pixels per second squared. Using Newton’s second law you can still work out exactly where your view will be at any time based on the gravity components you supply.

Do you really need to know all this? Not really; all you really need to know is that a bigger value for g means things will fall faster, but it never hurts to understand the math underneath.

Setting boundaries

Although you can’t see it, the square continues to fall even after it disappears off the bottom of your screen. In order to keep it within the bounds of the screen you need to define a boundary.

Add another instance variable in ViewController.m DynamicsPlaygroundViewController.cs:

UICollisionBehavior collision;

Add these lines to the bottom of viewDidLoad:

collision = new UICollisionBehavior (new [] { square });
collision.TranslatesReferenceBoundsIntoBoundary = true;
animator.AddBehavior (collision);

The above code creates a collision behavior, which defines one or more boundaries with which the associated items interact.

Rather than explicitly adding boundary co-ordinates, the above code sets the TranslatesReferenceBoundsIntoBoundary property to YES true. This causes the boundary to use the bounds of the reference view supplied to the UIDynamicAnimator.

Build and run; you’ll see the square collide with the bottom of the screen, bounce a little, then come to rest, as so:

SquareAtRest

That’s some pretty impressive behavior, especially when you consider just how little code you’ve added at this point.

Handling collisions

Next up you’ll add an immovable barrier that the falling square will collide and interact with.
Insert the following code to viewDidLoad just after the lines that add the square to the view:

UIView barrier = new UIView (new RectangleF (0, 300, 130, 20));
barrier.BackgroundColor = UIColor.Red;
this.View.AddSubview(barrier);

Build and run your app; you’ll see a red “barrier” extending halfway across the screen. However, it turns out the barrier isn’t that effective as the square falls straight through the barrier:

BadBarrier

That’s not quite the effect you were looking for, but it does provide an important reminder: dynamics only affect views that have been associated with behaviors.

Time for a quick diagram:

DynamicClasses

UIDynamicAnimator is associated with a reference view that provides the coordinate system. You then add one or more behaviors that exert forces on the items they are associated with. Most behaviors can be associated with multiple items, and each item can be associated with multiple behaviors. The above diagram shows the current behaviors and their associations within your app.

Neither of the behaviors in your current code is “aware” of the barrier, so as far as the underling dynamics engine is concerned, the barrier doesn’t even exist.

Making objects respond to collisions

To make the square collide with the barrier, find the line that initializes the collision behavior and replace it with the following:

collision = new UICollisionBehavior (new [] { square, barrier });

The collision object needs to know about every view it should interact with; therefore adding the barrier to the list of items allows the collision object to act upon the barrier as well.

Build and run your app; the two objects collide and interact, as shown in the following screenshot:

GoodBarrier

The collision behavior forms a “boundary” around each item that it’s associated with; this changes them from objects that can pass through each other into something more solid.

Updating the earlier diagram, you can see that the collision behavior is now associated with both views:

DynamicClasses2

However, there’s still something not quite right with the interaction between the two objects. The barrier is supposed to be immovable, but when the two objects collide in your current configuration the barrier is knocked out of place and starts spinning towards the bottom of the screen.

Even more oddly, the barrier bounces off the bottom of the screen and doesn’t quite settle down like the square—this makes sense because the gravity behavior doesn’t interact with the barrier. This also explains why the barrier doesn’t move until the square collides with it.

Looks like you need a different approach to the problem. Since the barrier view is immovable, there isn’t any need to for the dynamics engine to be aware of its existence. But how will the collision be detected?

Invisible boundaries and collisions

Change the collision behavior initialization back to its original form so that it’s only aware of the square:

collision = new UICollisionBehavior (new [] { square });

Next, add a boundary as follows:

// Add a boundary that coincides with the top edge
PointF rightEdge = new PointF(
    barrier.Frame.Location.X + barrier.Frame.Size.Width,
    barrier.Frame.Location.Y);
collision.AddBoundary(new NSString("barrier"),
    barrier.Frame.Location, rightEdge);

The above code adds an invisible boundary that coincides with the top edge of the barrier view. The red barrier remains visible to the user but not to the dynamics engine, while the boundary is visible to the dynamics engine but not the user. As the square falls, it appears to interact with the barrier, but it actually hits the immovable boundary line instead.

Build and run your app to see this in action, as below:

BestBarrier

The square now bounces off the boundary, spins a little, and then continues its journey towards the bottom of the screen where it comes to rest.

By now the power of UIKit Dynamics is becoming rather clear: you can accomplish quite a lot with only a few lines of code. There’s a lot going on under the hood; the next section shows you some of the details of how the dynamic engine interacts with the objects in your app.

Behind the scenes of collisions

Each dynamic behavior has an action property where you supply a block to be executed with every step of the animation. Add the following code to viewDidLoad:

collision.Action = new NSAction (delegate
{
	Console.WriteLine("{0}, {1}", square.Transform, square.Center);
});

The above code logs the center and transform properties for the falling square. Build and run your app, and you’ll see these log messages in the Xcode console window.

For the first ~400 milliseconds you should see log messages like the following:

2014-05-19 16:48:42.190 DynamicsPlayground[48788:70b] xx:1.0 yx:0.0 xy:0.0 yy:1.0 x0:0.0 y0:0.0, {X=150, Y=236}
2014-05-19 16:48:42.207 DynamicsPlayground[48788:70b] xx:1.0 yx:0.0 xy:0.0 yy:1.0 x0:0.0 y0:0.0, {X=150, Y=243}
2014-05-19 16:48:42.224 DynamicsPlayground[48788:70b] xx:1.0 yx:0.0 xy:0.0 yy:1.0 x0:0.0 y0:0.0, {X=150, Y=250}

Here you can see that the dynamics engine is changing the center of the square—that is, its frame—in each animation step.

As soon as the square hits the barrier, it starts to spin, which results in log messages like the following:

2014-05-25 16:15:37.904 DynamicsPlayground[5616:70b] xx:0.09 yx:1.0 xy:-1.0 yy:0.09 x0:0.0 y0:0.0, {X=197, Y=326}
2014-05-25 16:15:37.921 DynamicsPlayground[5616:70b] xx:0.03 yx:1.0 xy:-1.0 yy:0.03 x0:0.0 y0:0.0, {X=199, Y=332}
2014-05-25 16:15:37.938 DynamicsPlayground[5616:70b] xx:-0.03 yx:1.0 xy:-1.0 yy:-0.03 x0:0.0 y0:0.0, {X=201, Y=338}

Here you can see that the dynamics engine is using a combination of a transform and a frame offset to position the view according to the underlying physics model.

While the exact values that dynamics applies to these properties are probably of little interest, it’s important to know that they are being applied. As a result, if you programmatically change the frame or transform properties of your object, you can expect that these values will be overwritten. This means that you can’t use a transform to scale your object while it is under the control of dynamics.

The method signatures for the dynamic behaviors use the term items rather than views. The only requirement to apply dynamic behavior to an object is that it adopts the UIDynamicItem protocol implements the IUIDynamicItem interface.

Your class can do this by implementing the IUIDynamicItem directly or by inheriting from the UIDynamicItem abstract class.

Since the UIView class inherits from UIResponder, it implement the IUIDynamicItem interface.

The UIDynamicItem protocol IUIDynamicItem interface gives dynamics read and write access to the center and transform properties, allowing it to move the items based on its internal computations. It also has read access to bounds, which it uses to determine the size of the item. This allows it to create collision boundaries around the perimeter of the item as well as compute the item’s mass when forces are applied.

This means that dynamics is not tightly coupled to UIView; indeed there is another UIKit class that adopts this protocol implements this interfaceUICollectionViewLayoutAttributes. This allows dynamics to animate items within collection views.

Collision notifications

So far you have added a few views and behaviors then let dynamics take over. In this next step you will look at how to receive notifications when items collide.

Open ViewController.m DynamicsPlaygroundViewController.cs adopt the UICollisionBehaviorDelegate protocol.

Still in viewDidLoad, set the view controller as the delegate just after the collision behavior has been instantiated, as follows:

Next, add an implementation for one of the collision behavior delegate methods:

collision.BeganBoundaryContact += (object sender, UICollisionBeganBoundaryContactEventArgs e) => {
	Console.WriteLine("Boundary contact occurred - {0}", e.BoundaryIdentifier);
};

This delegate method is fired off when a collision occurs and prints out a log message to the console. In order to avoid cluttering up your console log with lots of messages, feel free to remove the _collision.action collision.Action logging you added in the previous section.

Build and run; your objects will interact, and you’ll see the following entries in your console:

2014-05-25 18:32:16.928 DynamicsPlayground[6956:70b] Boundary contact occurred - barrier
2014-05-25 18:32:17.144 DynamicsPlayground[6956:70b] Boundary contact occurred - barrier
2014-05-25 18:32:17.705 DynamicsPlayground[6956:70b] Boundary contact occurred - 
2014-05-25 18:32:17.804 DynamicsPlayground[6956:70b] Boundary contact occurred - 
2014-05-25 18:32:17.821 DynamicsPlayground[6956:70b] Boundary contact occurred - 
2014-05-25 18:32:18.071 DynamicsPlayground[6956:70b] Boundary contact occurred - 
2014-05-25 18:32:18.138 DynamicsPlayground[6956:70b] Boundary contact occurred - 
2014-05-25 18:32:18.154 DynamicsPlayground[6956:70b] Boundary contact occurred - 

From the log messages you can see that the square collides twice with the boundary identifier barrier; this is the invisible boundary you added earlier. The (null) lack of an identifier refers to the reference view boundary.

These log messages can be fascinating reading (seriously!), but it would be much more fun to provide a visual indication when the item bounces.

Below the line that sends message to the log, add the following:

UIView view = (UIView)e.DynamicItem;
view.BackgroundColor = UIColor.Yellow;
UIView.Animate(duration:0.3, animation:new NSAction (delegate
{
	view.BackgroundColor = UIColor.Gray;
}));

The above code changes the background color of the colliding item to yellow, and then fades it back to gray again.

Build and run to see this effect in action:

YellowCollision

The square will flash yellow each time it hits a boundary.

So far UIKit Dynamics has automatically set the physical properties of your items (such as mass or elasticity) by calculating them based on your item’s bounds. Next up you’ll see how you can control these physical properties yourself by using the UIDynamicItemBehavior class.

Configuring item properties

Within viewDidLoad, add the following to the end of the method:

UIDynamicItemBehavior itemBehaviour = new UIDynamicItemBehavior (new [] { square });
itemBehaviour.Elasticity = 0.6f;
animator.AddBehavior (itemBehaviour);

The above code creates an item behavior, associates it with the square, and then adds the behavior object to the animator. The elasticity property controls the bounciness of the item; a value of 1.0 represents a completely elastic collision; that is, where no energy or velocity is lost in a collision. You’ve set the elasticity of your square to 0.6, which means that the square will lose velocity with each bounce.

Build and run your app, and you’ll notice that the square now behaves in a bouncier manner, as below:

PrettyBounce

Note: If you are wondering how I produced the above image with trails that show the previous positions of the square, it was actually very easy! I simply added a block to the action property of one of the behaviors, and every fifth time the block code was executed, added a new square to the view using the current center and transform from the square.

In the above code you only changed the item’s elasticity; however, the item’s behavior class has a number of other properties that can be manipulated in code. They are as follows:

  • elasticity — determines how ‘elastic’ collisions will be, i.e. how bouncy or ‘rubbery’ the item behaves in collisions.
  • friction — determines the amount of resistance to movement when sliding along a surface.
  • density — when combined with size, this will give the overall mass of an item. The greater the mass, the harder it is to accelerate or decelerate an object.
  • resistance — determines the amount of resistance to any linear movement. This is in contrast to friction, which only applies to sliding movements.
  • angularResistance — determines the amount of resistance to any rotational movement.
  • allowsRotation — this is an interesting one that doesn’t model any real-world physics property. With this property set to NO the object will not rotate at all, regardless of any rotational forces that occur.

Adding behaviors dynamically

In its current state, your app sets up all of the behaviors of the system, then lets dynamics handle the physics of the system until all items come to rest. In this next step, you’ll see how behaviors can be added and removed dynamically.

Open ViewController.m DynamicsPlaygroundViewController.cs and add the following instance variable:

bool firstContact = true;

Add the following code to the end of the collision delegate method collisionBehavior:beganContactForItem:withBoundaryIdentifier:atPoint:

if (firstContact)
{
	firstContact = false;

	UIView square2 = new UIView (new RectangleF (30, 0, 100, 100));
	square2.BackgroundColor = UIColor.Gray;
	this.View.AddSubview(square2);

	collision.AddItem(square2);
	gravity.AddItem(square2);

	UIAttachmentBehavior attach = new UIAttachmentBehavior (view, square2);
	animator.AddBehavior(attach);
}

The above code detects the initial contact between the barrier and the square, creates a second square and adds it to the collision and gravity behaviors. In addition, you set up an attachment behavior to create the effect of attaching a pair of objects with a virtual spring.

Build and run your app; you should see a new square appear when the original square hits the barrier, as shown below:

Attachment

While there appears to be a connection between the two squares, you can’t actually see the connection as a line or spring since nothing has been drawn on the screen to represent it.

Where To Go From Here?

At this point you should have a solid understanding of the core concepts of UIKit Dynamics.

If you’re interested in learning more about UIKit Dynamics, check out our book iOS 7 By Tutorials. The book takes what you’ve learned so far and goes a step further, showing you how to apply UIKit Dynamics in an real world scenario:

SandwichFlowDynamics

The user can pull up on a recipe to take a peek at it, and when they release the recipe, it will either drop back into the stack, or dock to the top of the screen. The end result is an application with a real-world physical feel.

I hope you enjoyed this UIKit Dynamics tutorial – we think it’s pretty cool and look forward to seeing the creative ways you use it in your apps. If you have any questions or comments, please join the forum discussion below add a comment below or join the forum discussion of the original article.

The full sourcecode for the Objective-C version of Dynamics Playground you have built in this tutorial is available on github, with a commit for each ‘build and run’ step.

Posted in iPhone Dev | Tagged , , , | Leave a comment

Python: Compute and Prettily Display Difference Between Two Dates

#!/usr/bin/env python

import calendar
import datetime
import dateutil
import dateutil.parser
import os
import sys

def usage():
    print "Usage: %s start-date end-date" % (os.path.basename(sys.argv[0]))

def diff_dates(start, end):

    months = (end.year - start.year)*12 + end.month - start.month
    years  = months / 12
    months = months % 12
    days   = end.day - start.day

    if days < 0:
        months -= 1
        if months < 0:
            months  = 11
            years  -= 1
        days = calendar.monthrange(end.year, end.month)[1] + end.day - start.day

    return (years, months, days)

def pretty_diff(datetuple):

    (years, months, days) = datetuple

    value = ''
    if years == 1:
        value = "%d year" % (years)
    elif years > 0:
        value = "%d years" % (years)

    if months > 0:
        if len(value) > 0:
            value += ", "
        if months == 1:
            value += "%d month" % (months)
        else:
            value += "%d months" % (months)

    if days > 0 or len(value) == 0:
        if len(value) > 0:
            value += ", "
        if days == 1:
            value += "%d day" % (days)
        else:
            value += "%d days" % (days)

    return value

if __name__ == "__main__":

    if len(sys.argv) < 3:
        usage()
        sys.exit()

    start = dateutil.parser.parse(sys.argv[1]).date()
    end   = dateutil.parser.parse(sys.argv[2]).date()

    if start > end:
        diff  = diff_dates(end, start)
        print pretty_diff(diff)
    else:
        diff  = diff_dates(start, end)
        print pretty_diff(diff)    
Posted in Python | Tagged | Leave a comment

Xib-Free iOS App with C# – Part 4 – iAd

This is Part 4 of our series building a xib-free iOS app with C#.

In our last episode, we displayed and updated the current time based on an NSTimer. We experimented with timer periodicity and finally settled on using a cross-platform timer from System.Threading. Today, we will add an iAd banner to the app. Apple has made this really easy.

Xib-Free iAd Banner

Add an iAd banner view to the CurrentWeatherClockViewController:

    private ADBannerView adBannerView;

As we’ve done before, right-click ADBannerView and select Resolve > using MonoTouch.iAd to add the iAd framework.

Add the following code at the end of the ViewDidLoad method to create the ad banner and add it to the view:

    this.adBannerView = new ADBannerView (new Rectangle (0, 386, 320, 50));
    this.View.AddSubview (this.adBannerView);

Build and run. Wait a couple minutes and you’ll see ads. You can tap the ad to see some Apple promotional information that demonstrates some of the iAd capabilities.

If you examine the Application Output window, you will see errors like this:

ADBannerView: Unhandled error (no delegate or delegate does not implement didFailToReceiveAdWithError:): Error Domain=ADErrorDomain Code=3 "The operation couldn’t be completed. Ad inventory unavailable" UserInfo=0xf8af800 {ADInternalErrorCode=3, ADInternalErrorDomain=ADErrorDomain, NSLocalizedFailureReason=Ad inventory unavailable}

Implement the missing event handler by adding this code to the end of ViewDidLoad.

    this.adBannerView.FailedToReceiveAd += (object sender, AdErrorEventArgs e) => {
        Console.WriteLine (e.Error.LocalizedDescription);
    };

If you’ve done this in Objective-C, you’ll appreciate how easy that was!

Posted in iPhone Dev | Tagged , , , , , | Leave a comment

Xib-Free iOS App with C# – Part 3 – Timers

This is Part 3 of our series building a xib-free iOS app with C#.

In our last episode, we created a new project in Xamarin Studio, created a custom view controller, initialized its view, and added a clock view. Today, we will explore several ways to display and update the time.

Display the Current Time

To display the current time, add a method to the class CurrentWeatherClockViewController to update the clock view:

private void UpdateClockView()
{
    timeLabel.Text = String.Format ("{0:hh:mm:ss tt}", DateTime.Now);
}

Next, override the ViewWillAppear method of the super class, UIViewController:

public override void ViewWillAppear (bool animated)
{
    base.ViewWillAppear (animated);

    this.UpdateClockView ();
}

A shortcut for entering this method is to first type override. As soon as you type a space after override, Xamarin Studio will provide a completion list. Choose ViewWillAppear from that list. The IDE will then automatically insert a skeleton of the ViewWillAppear method, including the call to base.ViewWillAppear. All you have to do is add this line:

    this.UpdateClockView ();

When you build and run the project, your app will display the current time. But the time is still not being updated like a real clock. Let’s do that now.

Update the Current Time

To update the time, we need a timer. Add a private field:

    private NSTimer timer;

Note that the IDE sets NSTimer in red. Right click and choose Resolve > using MonoTouch.Foundation.

Add a method to start the timer:

private void StartTimer()
{
    this.timer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (1.0), delegate {
        this.UpdateClockView ();
    });
}

And start it by adding this line to ViewWillAppear:

    this.StartTimer ();

Your CurrentWeatherClockViewController class should look something like this now:

using System;
using System.Drawing;

using MonoTouch.UIKit;
using MonoTouch.Foundation;

namespace CurrentWeatherClock
{
    public class CurrentWeatherClockViewController : UIViewController
    {
        private UILabel timeLabel;
        private NSTimer timer;

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            this.View.BackgroundColor = UIColor.White;

            this.timeLabel = new UILabel
            {
                Frame = new RectangleF(0, 180, this.View.Bounds.Width, 100),
                Text = "00:00:00 AM",
                Font = UIFont.SystemFontOfSize(56)
            };

            this.View.AddSubview (this.timeLabel);
        }

        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);

            this.UpdateClockView ();
            this.StartTimer ();
        }

        private void UpdateClockView()
        {
            timeLabel.Text = String.Format ("{0:hh:mm:ss tt}", DateTime.Now);
        }

        private void StartTimer()
        {
            this.timer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (1.0), delegate {
                this.UpdateClockView ();
            });
        }
    }
}

Stop the Timer

Stop the timer in the ViewWillDisappear method:

public override void ViewWillDisappear (bool animated)
{
    base.ViewWillDisappear (animated);

    this.StopTimer ();
}

private void StopTimer()
{
    this.timer.Invalidate ();
}

It’s a good idea to stop timers, tasks, and other continuously running resources that a page is using when the user navigates away.

Timer Periodicity

Let’s take an informal look at whether our timer really is firing at a one second interval. Change the clock display format:

    timeLabel.Text = String.Format ("{0:hh:mm:ss.ff}", DateTime.Now);

Build and run. In my experiments, it looks pretty good on both the simulator and an iPhone device. However, let’s not take any chances. A common technique, when sampling a continuous fuction is to sample at twice the frequency1. The clock is not a true continuous function, but appears to be from our persepctive of displaying samples once per second.

Change the timer interval rate to one half second, then build and run again. Note that the clock is updated approximately every half second.

private void StartTimer()
{
    this.timer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (0.5), delegate {
        this.UpdateClockView ();
    });
}

Cross-Platform Timer

This timer works fine, but when using Xamarin and C#, we’d like to use the .Net libraries where we can. This makes the app more cross-platform in case we wish to port to Android later. Of course, Android does not have a UIViewController, so that will have to change anyway. But in a larger application, you likely would have implemented the timer in a separate class that could be cross-platform.

Replace the timer field:

    private Timer   timer;

This will require another using statement:

using System.Threading;

Replace the timer start and stop methods:

private void StartTimer()
{
    this.timer = new Timer(delegate {this.UpdateClockView();}, null, 0, 500);
}

private void StopTimer()
{
    if (this.timer != null)
    {
        this.timer.Change (Timeout.Infinite, Timeout.Infinite);
    }
}

(If you’re used to Objective-C, you might be tempted to leave out the test for null. C# doesn’t work that way. You’ll get a null exception if you try it.)

Build and run. Oops, we got an exception anyway:

MonoTouch.UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.

This happens because we’re updating the view on a thread other than the main thread. Fix it by invoking the assignment to the UILabel on the main thread:

private void UpdateClockView()
{
    InvokeOnMainThread (delegate
    {
        timeLabel.Text = String.Format ("{0:hh:mm:ss.ff}", DateTime.Now);
    });
}

Tweak the Timer Start

This is great, but let’s do one more tweak to make the one second updates better match other clocks. Delay starting the timer to about the start of a new second:

private void StartTimer()
{
    int dueTime = 1000 - DateTime.Now.Millisecond;
    this.timer = new Timer(delegate {this.UpdateClockView();}, null, dueTime, 500);
}

Restore AM/PM Indicator

And finally, let’s restore the AM/PM indicator:

    timeLabel.Text = String.Format ("{0:hh:mm:ss tt}", DateTime.Now);

Final Version with Timer

using System;
using System.Drawing;
using System.Threading;

using MonoTouch.UIKit;
using MonoTouch.Foundation;

namespace CurrentWeatherClock
{
    public class CurrentWeatherClockViewController : UIViewController
    {
        private UILabel timeLabel;
        private Timer   timer;

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            this.View.BackgroundColor = UIColor.White;

            this.timeLabel = new UILabel
            {
                Frame = new RectangleF(0, 180, this.View.Bounds.Width, 100),
                Text = "00:00:00 AM",
                Font = UIFont.SystemFontOfSize(56)
            };

            this.View.AddSubview (this.timeLabel);
        }

        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);

            this.UpdateClockView ();
            this.StartTimer ();
        }

        public override void ViewWillDisappear (bool animated)
        {
            base.ViewWillDisappear (animated);

            this.StopTimer ();
        }

        private void UpdateClockView()
        {
            InvokeOnMainThread (delegate
            {
                timeLabel.Text = String.Format ("{0:hh:mm:ss tt}", DateTime.Now);
            });
        }

        private void StartTimer()
        {
            int dueTime = 1000 - DateTime.Now.Millisecond;
            this.timer = new Timer(delegate {this.UpdateClockView();}, null, dueTime, 500);
        }

        private void StopTimer()
        {
            if (this.timer != null)
            {
                this.timer.Change (Timeout.Infinite, Timeout.Infinite);
            }
        }
    }
}

  1. The Nyquist frequency, named after electronic engineer Harry Nyquist, is ½ of the sampling rate of a discrete signal processing system. http://en.wikipedia.org/wiki/Nyquist_frequency&#160;
Posted in iPhone Dev | Tagged , , , , | Leave a comment

Xib-Free iOS App with C# – Part 2 – Clock

This is Part 2 of our series building a xib-free iOS app with C#.

Create a New Project in Xamarin Studio

Start by creating an iOS solution in Xamarin Studio using the iPhone Empty Project template just like you did last time when following the Xamarin article, Creating iOS Applications in Code. Name the project CurrentWeatherClock.

New Solution

Xamarin Studio will create a new solution, open it, and open the AppDelegate.cs file:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace CurrentWeatherClock
{
    // The UIApplicationDelegate for the application. This class is responsible for launching the
    // User Interface of the application, as well as listening (and optionally responding) to
    // application events from iOS.
    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        // class-level declarations
        UIWindow window;
        //
        // This method is invoked when the application has loaded and is ready to run. In this
        // method you should instantiate the window, load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method, or iOS will terminate your application.
        //
        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            // create a new window instance based on the screen size
            window = new UIWindow (UIScreen.MainScreen.Bounds);

            // If you have defined a root view controller, set it here:
            // window.RootViewController = myViewController;

            // make the window visible
            window.MakeKeyAndVisible ();

            return true;
        }
    }
}

If you build and run, you’ll get a black screen and an error message in the console window of Xamarin Studio:

Application windows are expected to have a root view controller at the end of application launch

Create a Custom View Controller

Add a new class named CurrentWeatherClockViewController via one of the following methods:

  • Select menu File > New > File
  • Press Command-N
  • Right click on the project and select menu option Add > New File…

CurrentWeatherClockViewController.cs

Edit your new class to add the MonoTouch.UIKit namespace and inherit from UIViewController:

using System;

using MonoTouch.UIKit;

namespace CurrentWeatherClock
{
    public class CurrentWeatherClockViewController : UIViewController
    {
        public CurrentWeatherClockViewController ()
        {
        }
    }
}

If you build and run at this point, you won’t see anything different because we haven’t hooked this view controller into the main window yet.

Initialize the View

Get rid of the constructor for now and override the ViewDidLoad method as follows:

using System;

using MonoTouch.UIKit;

namespace CurrentWeatherClock
{
    public class CurrentWeatherClockViewController : UIViewController
    {
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            this.View.BackgroundColor = UIColor.White;
        }
    }
}

Before you build and run, we need to create an object of this class and hook it into the main window’s RootViewController. Open the AppDelegate class and replace this code:

// If you have defined a root view controller, set it here:
// window.RootViewController = myViewController;

with this:

window.RootViewController = new CurrentWeatherClockViewController ();

Create and Add the Clock View

Add an instance of UILabel class:

private UILabel timeLabel;

Create the object and add it to the view controller’s view:

using System;
using System.Drawing;

using MonoTouch.UIKit;

namespace CurrentWeatherClock
{
    public class CurrentWeatherClockViewController : UIViewController
    {
        private UILabel timeLabel;

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            this.View.BackgroundColor = UIColor.White;

            this.timeLabel = new UILabel
            {
                Frame = new RectangleF(0, 180, this.View.Bounds.Width, 100),
                Text = "00:00:00 AM",
                Font = UIFont.SystemFontOfSize(56)
            };

            this.View.AddSubview (this.timeLabel);
        }
    }
}

Now when you build and run, you will be see your clock label on a white background. Congratulations, you’ve just created a xib-free iOS app in C#!

In the immortal words of Ron Popeil, “But wait, there’s more!”

Next time, we will discuss how to get the clock running and displaying the current time.

Posted in iPhone Dev | Tagged , , , , | Leave a comment

Convert Trunk Notes To Plain Markdown

This shell script converts one or more Trunk Notes files to plain markdown. It removes the first 7 lines and touches the modification date to match the Timestamp line. It does not convert the markdown itself. For example it does not convert ~~ (strikethrough).

It assumes the input files all have the extension .markdown and writes files with extension .md, thus not destroying your original files.

#!/bin/sh

# Converts one or more Trunk Notes to plain markdown

for file in $* ; do
    basename=$(basename $file .markdown)
    timestamp=$(egrep ^Timestamp: $file | tr -d "A-Za-z: +-" | cut -c -14)
    sed -e '1,7d' < $file > $basename.md
    touch -t ${timestamp:0:12}.${timestamp:12:14} $basename.md
done
Posted in Tools | Tagged , | Leave a comment