我正在构建一个大型故事板,我想知道是否有人为segue标识符提出了有用的命名约定。
看起来Apple只是在他们的例子中使用'ShowX',其中X是它所显示的视图的名称。到目前为止,我更喜欢使用'PushX'或'ModalX'来跟踪它的转换类型。任何人有任何其他技巧或提示?
这个问题没有正确的答案。这取决于口味。我减少了可读性。不要羞于为你的segue标识符命名;提供长而富有表现力的名称,因为Objective-C是一种非常冗长的语言,利用我们编写非常易读的代码。
我找了一个正式的会议,但我找不到。以下是苹果公司所说的话:
您可以在Interface Builder中为segue分配标识符。标识符是应用程序用于区分一个segue与另一个segue的字符串。例如,如果您有一个源视图控制器可以切换到两个或多个不同的目标视图控制器,您将为每个segue分配不同的标识符,以便源视图控制器的prepareForSegue:sender:方法可以区分它们并适当地准备每个segue 。
来自Ray Wenderlich's site的另一句话:
为segue提供唯一的标识符。 (它只需在源场景中是唯一的;不同的场景可以使用相同的标识符。)
选择标识符名称的有趣方法(参见上面的链接了解更多信息):
if ([segue.identifier isEqualToString:@"SegueIdentifierName"])
我喜欢这个,因为它就像一个TDD方法:写一个失败的测试,写一些代码来通过失败的测试,重构,重复。
与编程中的大多数内容一样,您可以使用任何您喜欢的名称。
但是,正如编程中的大多数事情一样,names matter和good names are hard。
这是我如何命名segues ...
像命名动作方法一样命名segues。根据他们的行为来命名。好的segue名称示例:
addUser
showReport
editAccount
composeMessage
reviewChanges
避免使用segue名称来描述被干扰的东西或它是如何工作的。
一些不好的segue名字的例子!!:
segueUserDetailViewController
- 避免这个!segueImageViewController
- 避免这个!RecipeViewControllerToIngredientViewController
- 避免这个!这些名称不好,因为它们明确说明了它们的实现。他们不是命名他们做什么,而是命名他们如何做。这是coupling的一种形式。
所以,如果你正在做的是“展示一个购物篮”,事实上这恰好是通过今天呈现一个ZZBasketViewController
完成的,这与调用者完全无关,并且只会给他们带来他们不关心的细节。也许明天它将用ZZShoppingItemsViewController
或STSuperConfigurableStuffList
完成。
所以:
showShopping
等名称。showBasketViewController
这样的名字。任何抽象的名称不必指定如何完成某些事情是不好的,因为然后调用者规定了被调用者必须如何工作。
这种耦合将:
如果有人随后忽略了耦合并更改了实现,那么给定的名称就会开始存在,并会误导未来的程序员查看代码,除非名称也被更改。
Segue是抽象,因此他们的名字不应该指代实现。
Swift和Objective C都使用camelCase
作为标识符。
_
或-
字符。在camelCase
中命名您的segues并给它们一个小写的第一个字母。
Segue名称在故事板中不需要是唯一的。名称只需要在特定场景(视图控制器)中是唯一的。
Ilea's answer提到这一点,引用Ray的网站:
它只需要在源场景中是唯一的;不同的场景可以使用相同的标识符。
...事实上,在故事板的许多场景中拥有相同的segue名称通常很有意义,因为你可能能够从许多场景中获得addLocation
。
这是我使用的东西。您可能有一个视图控制器,可以显示和编辑帐户信息:AccountVC
。没有什么可以阻止你从一个场景中有两个或更多个segues到达同一个其他视图控制器的场景:editAccount
和showAccount
。然后你的prepareForSegue:sender:
可以使用segue ID来适当地设置AccountVC
来编辑或只显示。
sender
因为segues是通过发件人调用的,所以他们感觉非常像动作消息。
利用segue的sender
在prepareForSegue:sender:
实现中配置目标视图控制器。这可以节省污染您的视图控制器的暂时状态。
以下是处理点按的表视图委托的示例:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Account *const account = [self accountAtIndexPath: indexPath];
[self performSegueWithIdentifier: showAccount sender: account];
}
这让你的prepare…
方法看起来像这样:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([showAccount isEqualToString: segue.identifier])
{
AccountViewController *accountVC = segue.destinationViewController;
accountVC.account = sender;
}
}
@"stringLiterals"
in performSegue:
calls如果你问“这是什么showAccount
?你的意思是@"showAccount"
,对吧?”。一个重要的提示是:使用文件范围变量作为segue名称。不要使用@"string literals"
。所以,在我的视图控制器的顶部,通常有一个这样的块:
DEFINE_KEY(showReport);
DEFINE_KEY(showPDF);
DEFINE_KEY(shareReport);
宏DEFINE_KEY
在我的项目的.pch
中,看起来像这样:
#define DEFINE_KEY(keyName) static NSString *const keyName = @#keyName
...它创建一个const NSString*
变量,其值等于其名称。 static
表示它仅在此“编译单元”中可用,并且在链接时不会污染全局名称空间。
如果你使用这样的变量,你就有了编译器。你不能错误地命名,因为它不会构建。代码完成将帮助您完成您开始的名称。您可以像修改任何其他变量一样重构名称。即使语法荧光笔也在你身边!
将目标视图控制器视为展开segue的异常处理程序。展开segue向上传播导航堆栈非常像异常传播调用堆栈。 segue寻找一个unwind处理程序,就像异常查找异常处理程序一样(catch块)。它正在寻找适合于展开segue类型的展开处理程序 - 再次,这就像搜索异常类型的异常处理程序一样。
重要的是,您可以让许多视图控制器实现相同的展开处理程序。展开将像第一个处理它的视图控制器的异常一样冒泡。
放松命名的通常建议就像unwindToMessageList
。这可能有意义,但是遵循“异常处理程序”这个比喻,通过它们处理的内容来命名展开处理程序是非常有用的。因此,unwindFromEventDetails
,unwindFromReport
或unwindFromCloseupImage
可能是一个很好的名字,描述了被抓住的东西。这些处理程序可以在多个可能的捕获站点实现。将使用导航层次结构自动选择适当的处理程序。
"ViewControllerAToViewControllerB"
例如,如果您有MasterViewController和DetailViewController,则segue标识符可以是:
"MasterToDetail"
我个人不会在前面使用动画类型,如果你改变动画,你需要回到代码。但是,如果在源控制器中将segue标识符声明为常量,则可以在以后更轻松地更改名称,而无需深入了解代码。
我通常使用我给控制器的名称,而没有“ViewController”。因此,RatingViewController将作为故事板“评级”。一个例外是展开segues,我将那些以“returnTo”开头的名称命名为目的地名称(“returnToRating”)。