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
来完成这一事实与来电者完全无关,只会给他们带来他们不知道的细节的负担'不在乎。也许明天它将通过ZZShoppingItemsViewController
或STSuperConfigurableStuffList
完成。
所以:
使用名称,例如showShopping
。
避免使用showBasketViewController
等名称。
所有编程的命名规则
通常抽象的意义在于用户不知道也不应该知道抽象是如何工作的。他们只知道它将为他们做什么——这对他们意味着什么。
任何抽象的名称不必要地指定必须如何完成某事是不好的,因为调用者规定了被调用者如何 必须工作。
这种耦合将:
用不需要的知识给调用者增加负担。 以不必要的方式任意限制被调用方的实现。 以一种无意义且成本高昂的方式将调用者与被调用者耦合,需要维护或将来移除。如果随后有人忽略耦合并更改实现,那么给定的名称就会开始撒谎,并且会误导查看代码的未来程序员,除非该名称也变了。
Segues 是抽象的。 Segue 名称不应引用实现。
遵循 Cocoa 的标识符约定
Swift 和 Objective C 都使用 camelCase
作为标识符。
_
或-
字符。
除类型、类和协议外,所有名称的首字母都应小写。
在camelCase
中命名你的segues,并给他们一个小写的第一个字母。
不需要唯一性
Segue 名称不需要在故事板中必须是唯一的。名称只需要在特定场景(视图控制器)中是唯一的。
Ilea's answer 提到这一点,引用自 Ray 的网站:
它只需要在源场景中是唯一的;不同的场景可以使用相同的标识符。
...事实上,在故事板的许多场景中使用相同的 segue 名称通常很有意义,因为您可以从多个场景中addLocation
。
有关命名和使用 Segues 的更多提示...
场景可以有>1个segue去相同其他场景
这是我有点用的东西。您可能有一个可以显示和编辑帐户信息的视图控制器:AccountVC
。没有什么能阻止您从一个场景中获得两个或更多的转场,这些转场进入这个相同其他视图控制器的场景: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;
在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
。这是有道理的,但是按照“异常处理程序”的比喻,根据它们正在处理的内容命名展开处理程序会非常有用。因此,unwindFromEventDetails
、unwindFromReport
或 unwindFromCloseupImage
可能是描述捕获内容的好名称。这些处理程序可以在多个可能的捕获点实现。将使用导航层次结构自动选择适当的处理程序。
【讨论】:
你确定宏在工作吗?对我来说,它编译为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 将数据传递给视图控制器