Swift 中代理方法的命名方式

作者:Soroush Khanlou,原文链接,原文日期:2016-09-27
译者:saitjr;校对:CMB;定稿:CMB

可以说 Swift 是 Objective-C 的后继之人,毕竟也算是师出同门。但是他们语法看来不像,用起来也不像,给人的感觉也不一样。有些在 Objective-C 上用得好端端的案例,在 Swift 上却看起来怪怪的,如方法命名。在 Objective-C 中,方法名尽量完整:

objective-c
[string dataUsingEncoding:NSUTF8StringEncoding];

在 Swift 2.2 中,这样调用看着就没那么优雅:

string.dataUsingEncoding(NSUTF8StringEncoding)

在 Swift 3 中,这个方法看起来就顺眼多了:

string.data(using: .utf8)

所以,像 Swift 3 中这样的命名方式,才是 Swift 的正确姿势。而 Objective-C 的方式也只适用于 Objective-C。我觉得这篇文章应该能帮你在新世界中修炼你的方法命名习惯。

无论是三方框架,还是平时开发中编写的代码,都应该更新为更为 Swift 的方式。下面,我将着重说一下代理的命名。

Swift 中代理的理解和 Objective-C 并不完全相同。Objective-C 偏向于 “发送者” 与 “接收者”。Apple 的 Objective-C 文档也倾向于这种方式。比如 UIResponderisFirstResponder 方法,文档上是这样解释的:

Returns a Boolean value indicating whether the receiver is the first responder.

返回一个接收者是否是第一响应者的标识(布尔值)。

所以,在设置 target-action 的时候,参数名理所当然的称为 sender

objective-c
- (void)buttonTapped:(UIButton *)sender {

代理方法的定义规则和这个类似:在 Objective-C 中,代理方法的第一个参数总是发送者。让我们来看看为什么会这样:如果你(接收者,即实现代理方法的对象)是多个相同类型对象的代理,那么你需要这个参数来进行区分。所以代理方法提供了第一个参数,方便分别处理。(译注:例如多个 UITextFielddelegate 都是 self 的时候,就需要进行区分是哪个 UITextField 调用的代理方法)。

下面我会用到 Backchannel SDK 中的例子,为了简单起见,我简化了一些类名。

这个 SDK 中代理方法分为两大类。第一类是事件触发的代理:

objective-c
- (void)messageFormDidTapCancel:(BAKMessageForm *)messageForm;

在 Swift 中,翻译为:

func messageFormDidTapCancel(_ messageForm: BAKMessageForm)

这要放在 Swift 3 中就不那么顺眼了。在 Swift 3 中,应该去调冗余部分(messageFrom 重复了),并且第一个参数应该有别名,而不应该用下划线代替。

第二类是事件触发,并且还带有部分数据的代理方法。对于这类,我举了以下两个例子:

objective-c
- (void)messageForm:(BAKMessageForm *)messageForm didTapPostWithDraft:(BAKDraft *)draft;
- (void)messageForm:(BAKMessageForm *)messageForm didTapAttachment:(BAKAttachment *)attachment;

在 Swift 中,翻译为:

func messageForm(_ messageForm: BAKMessageForm, didTapPostWithDraft draft: BAKDraft)
func messageForm(_ messageForm: BAKMessageForm, didTapAttachment attachment: BAKAttachment)

简直辣眼睛。为啥两个方法都叫 messageFrom?并且这个方法开头的名词也不合常理:一般建议名词是方法返回的对象类型(比如 NSStringdata(using:),就是返回的 Data)。但是这个例子中,却并不需要返回任何 “message form”。这里指的 “message form”其实应该是第一个参数的名字,真是个令人纠结的方法名。

其实这两种类型的代理方法,都可以通过将“sender”移到行末,把动词提到最前来解决命名的问题。对于第一个例子来说,是 sender 想告诉代理点击取消事件(didTapCancel),而不是 messageFormDidTapCancel,所以应该改为:

func didTapCancel(messageForm: BAKMessageForm)

这样看起来好多了。事件的名称被提在了最前作为方法名,能很直观的看出方法的作用。我觉得,最好再将介词作为参数别名,这样调用的时候就更优雅了:

func didTapCancel(on messageForm: BAKMessageForm)

目前我还没找到关于介词的使用规范。不过我会在不同情况下,选择使用“on”,“for”,“with”,“in”。用户是点击在表单“上”的,所以我觉得这里用“on”比较合适。

接下来再来看看,代理方法有数据返回的情况。将动词提到最前,选择合适的介词就能有效解决这个问题了。

之前是:

func messageForm(_ messageForm: BAKMessageForm, didTapPostWithDraft draft: BAKDraft)

而更 Swift 化的是:

func didTapPost(with draft: BAKDraft, on messageForm: BAKMessageForm)

func didTap(attachment: BAKAttachment, on messageForm: BAKMessageForm)

这种命名规则只是我归纳出来的,并没有经过他人印证,但我觉得这要比现在代理方法命名的规则要好得多。之后,我可能还会自己的 Swift 代理方法中使用这种规则。

下面列举了 UITableView 的 delegate 与 data source 方法,以及这些方法在未来可能的样子:

func numberOfSections(in tableView: UITableView) -> Int

numberOfSections 遵循了前文提到的规则,看起来很优雅。

但其余的方法看起来就不那么好了:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

更为漂亮的命名是:

func numberOfRows(inSection section: Int, in tableView: UITableView) -> Int
func cellForRow(at indexPath: IndexPath, in tableView: UITableView) -> UITableViewCell
func didSelectRow(at indexPath: IndexPath, in tableView: UITableView)

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容