Type Names as Storyboard IDs
A while back I got in the habit of using the names my of custom types as different identifiers in iOS and macOS storyboards.
This post looks at a couple examples of how this simple practice removes the need for unnecessary strings and leads to cleaner code.
Storyboard Identifier
In the first example I’ve added a new UITableViewController
to my storyboard, set the Class to CustomTableViewController
and the Storyboard ID to “CustomTableViewController”
I can now programmatically create a new instance of CustomTableViewController
using its Storyboard ID:
var storyboardId = "CustomTableViewController";
var controller = Storyboard.InstantiateViewController (storyboardId) as CustomTableViewController;
Everything works as expected, as long as I have a view controller in my storyboard with a matching Storyboard ID, and there isn’t a typo in the string.
However, if I know that the Storyboard ID is the same as the type’s name, I can use the typeof
operator and get rid of the string altogether:
var storyboardId = typeof(CustomTableViewController).Name;
var controller = Storyboard.InstantiateViewController (storyboardId) as CustomTableViewController;
Or even better, write an extension method like this:
public static T Instantiate<T> (this UIStoryboard storyboard)
where T : UIViewController
=> storyboard.InstantiateViewController (typeof (T).Name) as T;
And cut the code down to:
var controller = Storyboard.Instantiate<CustomTableViewController>();
Now, I not only got rid of the string identifier, but I’ll also get build-time checking that my custom type inherits from UIViewController
.
Reuse Identifier
An even more common example of benefiting from this practice, is in the context of Reuse IDs on UITableView
or UICollectionView
cells. Take the UITableViewCell
subclass below.
public class CustomTableViewCell : UITableViewCell
{
public void SetData(Item item) => titleLabel.Text = item?.Name;
}
In my storyboard, I’ve set the CustomTableViewController
’s prototype cell’s Class to CustomTableViewCell
:
Then set the cell’s Reuse ID to “CustomTableViewCell”
Normally, my CustomTableViewController
(or UITableViewDataSource
) GetCell
override would look something like this:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var reuseId = "CustomTableViewCell";
var cell = tableView.DequeueReusableCell (reuseId, indexPath) as CustomTableViewCell;
cell?.SetData (Items [indexPath.Row]);
return cell;
}
However again, if I know that the Reuse ID is the same as the cell type’s name, I can get rid of the string, and write another extension method:
public static T Dequeue<T> (this UITableView tableView, NSIndexPath indexPath)
where T : UITableViewCell
=> tableView.DequeueReusableCell (typeof (T).Name, indexPath) as T;
And cut my GetCell
override to the code below, with the build-time checks:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.Dequeue<CustomTableViewCell>(indexPath);
cell?.SetData (Items [indexPath.Row]);
return cell;
}
Dig it?
You can find a the extension methods mention above and several more including support for collection views, here.