Storyboard Segue 标识符命名约定

Posted

技术标签:

【中文标题】Storyboard Segue 标识符命名约定【英文标题】:Storyboard Segue Identifier naming conventions 【发布时间】:2013-03-12 19:15:22 【问题描述】:

我正在构建一个大型故事板,我想知道是否有人提出了有用的segue 标识符的命名约定

看起来 Apple 在他们的示例中只使用了“ShowX”,其中 X 是它正在显示的视图的名称。到目前为止,我更喜欢使用“PushX”或“ModalX”来跟踪它是哪种类型的过渡。谁有其他的技巧或技巧?

【问题讨论】:

【参考方案1】:

与编程中的大多数事情一样,您可以使用任何您喜欢的名称。

但是,与编程中的大多数事情一样,names matter 和 good names are hard。

我是这样命名segues的……

好的segue名称

按照您命名操作方法的方式命名 segues。按照他们将要做什么来命名segues。好的 segue 名称示例:

addUser showReport editAccount composeMessage reviewChanges

错误的 segue 名称

避免只描述被连接到的东西是什么或它是如何工作的连接名称。

错误的 segue 名称的一些示例!

坏名字 1! – segueUserDetailViewController – 避免这种情况! 坏名声2! – segueImageViewController – 避免这种情况! 坏名声 3! – RecipeViewControllerToIngredientViewController – 避免这种情况!

为什么这些名字不好?

这些名称不好,因为它们明确说明了它们的实现。他们没有说出他们做了什么,而是说出了他们是如何做到的。这是coupling 的一种形式。

因此,如果您正在做的是“展示购物篮”,那么今天恰好通过展示ZZBasketViewController 来完成这一事实与来电者完全无关,只会给他们带来他们不知道的细节的负担'不在乎。也许明天它将通过ZZShoppingItemsViewControllerSTSuperConfigurableStuffList 完成。

所以:

使用名称,例如showShopping避免使用showBasketViewController等名称。

所有编程的命名规则

通常抽象的意义在于用户不知道也不应该知道抽象是如何工作的。他们只知道它将为他们做什么——这对他们意味着什么。

任何抽象的名称​​不必要地指定必须如何完成某事是不好的,因为调用者规定了被调用者如何 必须工作。

这种耦合将:

用不需要的知识给调用者增加负担。 以不必要的方式任意限制被调用方的实现。 以一种无意义且成本高昂的方式将调用者与被调用者耦合,需要维护或将来移除。

如果随后有人忽略耦合并更改实现,那么给定的名称就会开始撒谎,并且会误导查看代码的未来程序员,除非该名称也变了。

Segues 是抽象的。 Segue 名称不应引用实现。

遵循 Cocoa 的标识符约定

Swift 和 Objective C 都使用 camelCase 作为标识符。

名称中不得包含_- 字符。 除类型、类和协议外,所有名称的首字母都应小写。

camelCase 中命名你的segues,并给他们一个小写的第一个字母。

不需要唯一性

Segue 名称不需要在故事板中必须是唯一的。名称只需要在特定场景(视图控制器)中是唯一的。

Ilea's answer 提到这一点,引用自 Ray 的网站:

它只需要在源场景中是唯一的;不同的场景可以使用相同的标识符。

...事实上,在故事板的许多场景中使用相同的 segue 名称通常很有意义,因为您可以从多个场景中addLocation


有关命名和使用 Segues 的更多提示...

场景可以有>1个segue去相同其他场景

这是我有点用的东西。您可能有一个可以显示和编辑帐户信息的视图控制器:AccountVC。没有什么能阻止您从一个场景中获得两个或更多的转场,这些转场进入这个相同其他视图控制器的场景:editAccountshowAccount。然后,您的 prepareForSegue:sender: 可以使用 segue ID 适当地设置 AccountVC 以进行编辑或仅显示。

使用sender

因为 segues 是与发送者一起调用的,所以它们感觉非常像操作消息

利用segue 的senderprepareForSegue: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;
  

performSegue: 调用中避免@"stringLiterals"

如果你问“这是什么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 表示它只在这个“编译单元”中可用,并且在链接时不会污染全局命名空间。

如果您使用这样的变量,则编译器就在您身边。你不能把名字弄错,因为那样它就不会建立。代码完成将帮助您完成您开始的名称。您可以像重构任何其他变量一样重构名称。甚至语法高亮都在你身边!

将 unwind segues 视为异常

将目标视图控制器视为展开转场的异常处理程序。 unwind segue 向上传播导航堆栈,就像异常向上传播调用堆栈一样。 segue 寻找一个展开处理程序,就像一个异常寻找一个异常处理程序(catch 块)一样。它正在寻找一个适合 unwind segue 类型的 unwind 处理程序——同样,这就像一个用于正在搜索的异常类型的异常处理程序。

重要的是,您可以让许多视图控制器实现相同的展开处理程序。展开将像第一个处理它的视图控制器的异常一样冒泡。

展开命名的通常建议类似于unwindToMessageList。这是有道理的,但是按照“异常处理程序”的比喻,根据它们正在处理的内容命名展开处理程序会非常有用。因此,unwindFromEventDetailsunwindFromReportunwindFromCloseupImage 可能是描述捕获内容的好名称。这些处理程序可以在多个可能的捕获点实现。将使用导航层次结构自动选择适当的处理程序。

【讨论】:

你确定宏在工作吗?对我来说,它编译为static NSString *const test = @"keyName" @IulianOnofrei 好吧,这就是我正在使用的,如果按照您的建议扩展宏,则会出错。我无法检查输出,因为 Xcode 的该功能目前似乎不起作用!这是我目前的定义:#define DEFINE_KEY(keyName) NSString *const keyName = @#keyName 你能给我指出一个关于#在那里应用时正在做什么的文档吗?而且,您的意思是预处理助手视图不起作用吗? 是的,助手视图不起作用。这里的# 是预处理器"stringification" or "stringizer" operator。它应该扩展为包含宏变量捕获值的文字字符串。【参考方案2】:

这个问题没有正确答案。这取决于口味。我减轻了可读性。不要羞于给你的 segue 标识符起一个长名字;给出长而富有表现力的名称,因为 Objective-C 是一种非常冗长的语言,它利用我们编写非常易读的代码。

我搜索了一个正式的约定,但找不到。以下是苹果要说的:

您在 Interface Builder 中为您的 segue 分配标识符。一个 标识符是您的应用程序用来区分一个字符串 从另一个开始。例如,如果您有一个源视图控制器 可以连接到两个或多个不同的目标视图控制器, 您将为每个 segue 分配不同的标识符,以便 源视图控制器的 prepareForSegue:sender: 方法可以告诉 将它们分开并适当地准备每个 segue。

来自Ray Wenderlich's site的另一句话:

给 segue 一个唯一的标识符。 (它只需要在 源场景;不同的场景可以使用相同的标识符。)

一种有趣的选择标识符名称的方法(有关更多信息,请参见上面的链接):

    首先编写验证 segue 标识符名称的代码,然后再在界面生成器中设置名称。我说的是这段代码:if ([segue.identifier isEqualToString:@"SegueIdentifierName"])

    构建并运行!暂时不要在 Interface Builder 中填写标识符名称。你这样做是因为你可能有多个来自一个视图控制器的传出 segue,你需要能够区分它们。如果在您运行并触发您正在处理的 segue 时没有任何反应,那么您的 segue 名称标识符是唯一的并且很好用。相反,如果代码执行了您不希望的转场,则您的转场名称标识符存在冲突。

    修复冲突 - 如果有的话。

    在 Interface Builder 中填写 segue 标识符并测试它是否符合您的要求。

我喜欢这个,因为它就像一个 TDD 方法:编写一个失败的测试,编写一些代码来通过失败的测试,重构,重复。

【讨论】:

第 1 点应该说:if ([segue.identifier isEqualToString:@"SegueIdentifierName"])【参考方案3】:
"ViewControllerAToViewControllerB"

例如,如果您有一个 MasterViewController 和一个 DetailViewController,则 segue 标识符可能是:

"MasterToDetail"

【讨论】:

【参考方案4】:

我个人不会使用前面的animation-type,如果你改变了动画,你需要回到代码。但是,如果您在源控制器中将 segue 标识符声明为常量,则可以在以后更轻松地更改名称,而无需深入研究代码。

我通常使用我给控制器的名称,没有“ViewController”。所以 RatingViewController 将是“评级”作为故事板。一个例外是 unwind segues,我将它们命名为以“returnTo”开头并以目的地名称结尾的那些(“returnToRating”)。

【讨论】:

如果展开可以返回到两个不同的控制器,那么这不是一个好的命名方案。告诉您何时编辑歌曲标题,这可能是从专辑或歌曲表中完成的。在这种情况下,名称应该是 returnFromEditSongTitle

以上是关于Storyboard Segue 标识符命名约定的主要内容,如果未能解决你的问题,请参考以下文章

iOS如何获取对带有segue的storyboard容器中嵌入的视图控制器的引用?

使用 Storyboard Segue iOS 将数据传递给视图控制器

Xcode,在哪里分配 segue 标识符

C++,Java编程中 标识符 常见命名约定

有没有办法在 Xcode Storyboard 属性检查器中使用 plist 文件字符串?

什么是Segue