Storyboarding

hsoi blog, talk 0 Comments

I’m playing around with Xcode 4’s Storyboarding feature.

Essentially, it’s the direction Apple appears to be going for designing iOS application interfaces. Whereas the old nib/xib approach was “one screen in isolation” and you had to string everything together, with Storyboarding there’s generally a single file that defines the whole of the GUI for the app: each screen, the transitions to get to each screen.

Granted, my impressions here are only after playing with it for a few hours, but I felt they were worth jotting down.

I think Storyboarding is cool. The way iOS apps work (traditional apps, not things like games), it just makes sense to have this “all in one” file that defines all of the screens/views and how the flow of the app works. It’s cool to be able to look at the one file and see the entire flow of the app. Great for prototyping and getting the 100′ view of the app.

As well, it seems to be striving to handle more of those mundane tasks for us. While Apple’s done well to alleviate a lot of redundant coding, there’s still a fare share of it. Storyboarding seems to be striving towards alleviating some of that constant boilerplate behavior that we all have to do every single time we wish to do something — biggest of which is transitioning to the next screen/view.

So I think this is good.

But it does seem like a 1.0 or maybe even a 0.9 release.

For example, let’s say I wanted to put up a modal view. A common thing to want to do from that model view is to dismiss it! How can I do that? There’s no simple way to do it. You have to hook up your own Done button to its own IBAction. Fair enough I guess, and maybe I don’t understand all of the developer scenarios that could take place here. But I think about how there’s a -prepareForSegue:sender: method and why couldn’t the same be used here? That is, I’m in viewA, I tap some button which puts up viewB modally. Why can’t I tap viewB’s “Done” button and have it segue back to viewA, perhaps using -prepareForSegue:sender: to handle any work? like if viewA is a master and viewB is a detail, that A’s segue passes the data to B, and B’s segue passes the modified data back to A? Why isn’t there a way to handle that?

Furthermore, why can’t that code be written/edited within the Storyboard? Perhaps a block. May not be possible, but the notion just popped into my head as I wrote this.

Another example is the Edit button. So I have a UITableViewController and my table, all within a UINavigationController. I want to put an “Edit” button up there to allow the user to move/delete table rows. Well, I CAN get an edit button there, but it’s not THE edit button. Why can’t this all just be there and work nice and automagically? Sure, the actual delete/move delegate methods need to be implemented so the data model can be properly contended with, but again, all of the GUI fiddling, why can’t the storyboard handle it?

Another thing that got me was a table/navigation interface. I have a table, each cell as a detail disclosure indicator. I want tapping the indicator to segue to another view that shows the detail of the cell data. Well, I used the segue controls within the storyboard editor and was able to get the segue to work, BUT, it worked on tapping the cell. There doesn’t seem to be way to set up tapping on the detail disclosure indicator. Oh sure I can do it in code, but again the storyboard ought to allow for this.

Updated: I still say it’d be useful of the storyboard feature could allow setting the segue to happen off the detail disclosure indicator. But here is what I found. In my case I was setting the segue from the UITableViewCell to the new ViewController. Thus tapping the cell segued to the new ViewController, which isn’t what I wanted. In my case, tapping the cell did something else entirely (nothing I could storyboard) and thus the cell had the detail disclosure indicator and tapping THAT should move to the new ViewController (a “detail” view). With a little searching on Apple’s devforums I found the solution was instead to set the segue from the table’s ViewController (not the cell) to the detail ViewController. Then in -tableView:accessoryButtonTappedForRowWithIndexPath:, I manually invoke the segue (by its identifier) and pass the given NSIndexPath as the segue’s sender (be sure to -isKindOfClass: check it before using it). And hey, that seems to be working. (end Updated)

Again, I’ve only been playing with it for a few hours, so maybe all this magic is there and I just haven’t found it.

I think there’s great potential here and I’ll be watching to see where Storyboarding goes.

Updated: I’ve been playing with it a bit more, working on bringing a simple little project to life. And well… it’s kinda quirky, but I’m figuring some things out. For instance, while dealing with the above problem with the table segue, one thing I wanted to do was perhaps have no segue at all, just manually push it. So I’d have the next UIViewController just float in space in the storyboard and then deal with it. I wanted to set an IBOutlet to that controller, but there seems to be no way to do that — by design. I guess that makes sense, tho it’s frustrating, but I think if it was there it’d break a lot of the paradigm and proper encapsulation, so I reckon it’s good that you can’t do it.

But I figured there HAD to be some way to allow for that. In finding my solution to the problem I saw this snippet:

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    EditViewController *evc = [self.storyboard instantiateViewControllerWithIdentifier:@"EditViewControllerID"]; 
    [self.navigationController pushViewController:evc animated:YES];
}

So there you go.

I figured that many things were possible, just a matter of figuring it all out.

Leave a Reply