Wednesday, February 29, 2012

MonoTouch.Dialog UIPicker

In iOS a UIPicker looks like this:

I'm working on an iPhone application that's built using MonoTouch.Dialog and after a full day of trying to get the MonoTouch.Dialog compatible Picker in ClanceyLib to work, I've decided to package up my work and release it on GitHub.

The main issues with ClanceyLib is that it requires a heavily modified and out of date version of MonoTouch.Dialog. If you try to compile it with the built-in version of MonoTouch.Dialog you'll get the following two errors:

/Users/guivho/Mono/ClanceyLib/ClanceysLib/MT.D/ButtonElement.cs(49,49):
Error CS0115: `ClanceysLib.ButtonElement.GetCell(MonoTouch.Dialog.DialogViewController,
MonoTouch.UIKit.UITableView)' is marked as an override but no suitable
method found to override (CS0115) (ClanceysLib)


/Users/guivho/Mono/ClanceyLib/ClanceysLib/MT.D/ComboBoxElement.cs(49,49):
Error CS0115: `ClanceysLib.ComboBoxElement.GetCell(MonoTouch.Dialog.DialogViewController,
MonoTouch.UIKit.UITableView)' is marked as an override but no suitable
method found to override (CS0115) (ClanceysLib)


Ripping out the elements you need from ClanceyLib wasn't as easy as I hoped on the first try but I now have it working along with some other improvements:
  • Updated it to hide the keyboard or picker when selecting different cells to edit.
  • Changed so the Items in the Picker list are UIView's for greater customization.
  • Actually has a sample of how to use it. ;)
UPDATE 3/1/2012: It works out of the box with the version of MonoTouch.Dialog that is now packaged with MonoTouch. But, it will not dismiss the picker when selecting a different cell. To enable that feature it requires a custom version of MonoTouch.Dialog and you'll need to comment in 3 lines of code in PickerElement.cs.

I sent a pull request to get my minor change to MonoTouch.Dialog included in the core. If/when it's pulled I will update PickerElement.cs to take advantage of it and the dependency on the custom version of MonoTouch.Dialog will be no more. ;)

Thursday, February 9, 2012

setTimeout Setting Mysterious Callback Parameters

I got burned by this twice in the last month.

Say you want to call the following function after 5 seconds.
function doSomething(optionalParam) {
  // check if optional param passed in.
  if (optionalParam) {
    optionalParam.foo(); // this is where the error sometimes happens.
  }
  // do more stuff.
}

// delay 5 seconds.
setTimeout(doSomething, 5000);

Periodically I was getting undefined errors when trying to call foo(). After some googling, it turns out Gecko browsers have setTimeout pass back an extra parameter indicating the "actual lateness" of the timeout in milliseconds.
https://developer.mozilla.org/en/DOM/window.setTimeout

I haven't run into this with other browsers but to avoid the issue it's best to do the following when your callback functions have optional params (Not having optional params would obviously be even safer).
// delay 5 seconds.
setTimeout(function() {
  doSomething();
}, 5000);