Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storyboard Segue Identifier naming conventions

I'm building a large storyboard and I was wondering if anyone has come up with helpful naming conventions for segue identifiers.

It looks like Apple just uses 'ShowX' in their examples where X is the name of the view it is showing. So far I prefer to use 'PushX' or 'ModalX' to keep track of which type of transition it is. Anyone have any other tricks or tips?

like image 378
Steve Moser Avatar asked Mar 12 '13 19:03

Steve Moser


People also ask

How do you give a segue an identifier in a storyboard?

Assigning an identifier for the segue:Select the segue, from the attribute inspector you'll see "Identifier" text field, that's it! make sure to insert the exact same name that used in performSegueWithIdentifier .

What are some conventions for naming identifiers?

There are some rules you have to follow for naming identifiers: The first character of the identifier must be a letter of the alphabet (upper or lowercase) or an underscore ('_'). The rest of the identifier name can consist of letters (upper or lowercase), underscores ('_') or digits (0-9).

What is the purpose of giving a segue an identifier?

Use segues to define the flow of your app's interface. A segue defines a transition between two view controllers in your app's storyboard file. The starting point of a segue is the button, table row, or gesture recognizer that initiates the segue.


2 Answers

As with most things in programming, you can use any name you like.

But, as with most things in programming, names matter and good names are hard.

Here's how I name segues…

Good segue names

Name segues as you would name action methods. Name segues by what they will do. Good segue name examples:

  • addUser
  • showReport
  • editAccount
  • composeMessage
  • reviewChanges

Bad segue names

Avoid segue names that just describe what the segued to thing is or how it works.

Some examples of bad segue names!!:

  • Bad name 1! – segueUserDetailViewController – avoid this!
  • Bad name 2! – segueImageViewController – avoid this!
  • Bad name 3! – RecipeViewControllerToIngredientViewController – avoid this!

Why are these names bad?

These names are bad because they explicitly state their implementation. Instead of naming what they do, they name how they do it. This is a form of coupling.

So, if what you are doing is "showing a shopping basket", the fact that this happens to be done by presenting a ZZBasketViewController today, is totally irrelevant to the caller, and just burdens them with detail they don't care about. Perhaps tomorrow it'll be done with a ZZShoppingItemsViewController or an STSuperConfigurableStuffList.

So:

  • Use a name such as showShopping.
  • Avoid a name such as showBasketViewController.

A naming rule for all your programming

Usually the point of an abstraction is that a user doesn't and shouldn't know how the abstraction works. All they know is what it will do for them – what it means to them.

It is bad for any abstraction's name to needlessly specify how something must be done because then the caller prescribes how the callee must work.

This coupling will:

  • Burden the caller with knowledge it does not need.
  • Arbitrarily constrain the callee's implementation in a needless way.
  • Couple the caller to the callee in a pointless and costly way requiring maintenance or future removal.

If someone subsequently ignores the coupling and changes the implementation, then the given name begins to lie and will mislead a future programmer who looks at the code, unless the name is also changed.

Segues are abstractions. Segue names should not refer to the implementation.

Follow Cocoa's identifier convention

Both Swift and Objective C use camelCase for identifiers.

  • Names never contain _ or - characters.
  • With the exception of types, classes & protocols, all names should have a lower case first letter.

Name your segues in camelCase and give them a lower case first letter.

Uniqueness is not necessary

Segue names do not need to be unique within a storyboard. The names only need to be unique within a particular scene (view controller).

Ilea's answer mentions this, quoting from Ray's site:

It only has to be unique in the source scene; different scenes can use the same identifier.

…in fact, it often makes a lot of sense to have the same segue name in many scenes of a storyboard because you might be able to addLocation from a number of scenes.


Further tips for naming and working with Segues…

Scenes can have >1 segue going to the same other scene

This is something that I use a bit. You might have a view controller that can display and also edit account information: AccountVC. Nothing stops you having two or more segues from a scene that go to this same other view controller's scene: editAccount and showAccount. Your prepareForSegue:sender: can then use the segue ID to set up the AccountVC appropriately to either edit or just show.

Use the sender

Because segues are called with a sender, they feel very much like action messages.

Make use of the segue's sender to configure the destination view controller in your prepareForSegue:sender: implementation. This saves polluting your view controller with transitory state for this.

Here's an example of a table view delegate handling a tap:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {   Account *const account = [self accountAtIndexPath: indexPath];   [self performSegueWithIdentifier: showAccount sender: account]; } 

Which lets your prepare… method look like this:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {   if([showAccount isEqualToString: segue.identifier])   {     AccountViewController *accountVC = segue.destinationViewController;     accountVC.account = sender;   } } 

Avoid @"stringLiterals" in performSegue: calls

If you're asking "What's this showAccount? You mean @"showAccount", right?". A big tip is: Use file scope variables for your segue names. Do not use @"string literals". So, at the top of my view controllers there's often a block like this:

DEFINE_KEY(showReport); DEFINE_KEY(showPDF); DEFINE_KEY(shareReport); 

The macro DEFINE_KEY is in my project's .pch and looks like this:

#define DEFINE_KEY(keyName) static NSString *const keyName = @#keyName 

… it creates a const NSString* variable who's value is equal to its name. The static means that it's only available in this "compilation unit" and doesn't pollute the global name space at link time.

If you use a variable like this, you have the compiler on your side. You can't get a name wrong because then it won't build. Code completion will help you finish a name that you start. You can refactor a name as you would any other variable. Even the syntax highlighter is on your side!

Think of unwind segues as like exceptions

Think of the destination view controller as being an exception handler for the unwind segue. The unwind segue propagates up the navigation stack very much like an exception propagates up the call stack. The segue looks for an unwind handler like an exception looks for an exception handler (catch block). It's looking for an unwind handler that is suitable for the type of unwind segue – again, this is like an exception handler for the type of exception being searched for.

Importantly, you can have many view controllers implementing the same unwind handler. The unwind will bubble up like an exception to the first view controller that handles it.

The usual advice for unwind naming is something like unwindToMessageList. This can make sense, but following the "exception handler" metaphor, it can be very useful to name unwind handlers by what they are handling. So, unwindFromEventDetails, unwindFromReport, or unwindFromCloseupImage might be good names describing what is being caught. These handlers can be implemented at multiple possible catch sites. The appropriate handler will be automatically selected using the navigation hierarchy.

like image 136
Benjohn Avatar answered Oct 05 '22 21:10

Benjohn


There is no correct answer for this question. It depends on taste. I mitigate for readability. Don't be shy to give a long name for your segue identifier; give long and expressive names because Objective-C is a very verbose language leveraging us to write very readable code.

I have searched for an official convention, but I couldn't find any. Here's what Apple has to say:

You assign identifiers to your segues in Interface Builder. An identifier is a string that your application uses to distinguish one segue from another. For example, if you have a source view controller that can segue to two or more different destination view controllers, you would assign different identifiers to each segue so that the source view controller’s prepareForSegue:sender: method could tell them apart and prepare each segue appropriately.

Another quote from Ray Wenderlich's site:

Give the segue a unique Identifier. (It only has to be unique in the source scene; different scenes can use the same identifier.)

An interesting approach for picking the identifier name (see above link for more):

  1. First write the code that verifies for the segue identifier name BEFORE you even set the name in the interface builder. I'm talking about this code: if ([segue.identifier isEqualToString:@"SegueIdentifierName"])

  2. Build & Run! Don't fill in the identifier name in the Interface Builder yet. You do this because you may have multiple outgoing segues from one view controller and you’ll need to be able to distinguish between them. If nothing happens while you run and trigger the segue you're working on, then your segue name identifier is unique and good to be used. If instead the code performs a segue that you haven't intended, you have a conflict for the sague name identifier.

  3. Fix the conflict - if any.

  4. Fill in the segue identifier in the Interface Builder and test that it does what you want.

I like this because it's like a TDD approach: write a failing test, write some code to pass the failing test, refactor, repeat.

like image 39
Ilea Cristian Avatar answered Oct 05 '22 19:10

Ilea Cristian