2014-10-11 36 views
107

可以使用扩展为现有Swift对象类型添加扩展,如language specification中所述。命名为现有对象添加扩展名的Swift文件的最佳做法是什么?

其结果是,它可以创建扩展,如:

extension String { 
    var utf8data:NSData { 
     return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! 
    } 
} 

然而,什么是对含有这种扩展斯威夫特源文件的最好的命名方式?

过去,约定将extendedtype+categoryname.m用于Objective-C 类型,如the Objective-C guide中所述。但Swift示例没有类别名称,并称它为String.swift似乎不合适。

所以问题是:鉴于上述String扩展名,应该调用什么swift源文件?

+2

这不是一个codereview问题 - 我不关心这个特定的例子,我想知道什么是快速命名约定。 – AlBlue 2014-10-11 22:10:48

+2

没有命名约定。我们唯一需要做的就是Objective-C的类别,它们总是遵循'ClassName + ExtensionName'格式,并且我没有看到太多人仍在使用它。此外,我发现笨重的代替只是将类和扩展定义在一起,或者给文件一个更好的名字,比如'FooAbleTypes'和定义实例。 – CodaFi 2014-10-11 22:17:18

+4

有*是*没有命名的做法。以下是一个想法:将所有全局扩展集中在一个'Extensions.swift'中。这样,你就不会失去他们的踪迹,新代码将立即注意到他们。我宁愿将一次性扩展保留为需要的文件的私有文件。 – Andrew 2014-10-11 22:38:30

回答

123

我见过的大多数例子都模仿Objective-C方法。上面的例子中扩展将是:

String+UTF8Data.swift

的优点是,命名惯例可以很容易地理解,这是一个扩展,并且其类正在扩展。

使用Extensions.swift甚至StringExtensions.swift的问题在于,无法通过名称的内容来推断文件名称的目的。

使用xxxable.swift方法由Java使用,对于只能定义方法的协议或扩展才行。但是,上面的示例再次定义了一个属性,因此UTF8Dataable.swift没有太大的语法意义。

+1

尽管人们可以通过命名约定来推断正在扩展的内容,但IHMO是一个不必要的复杂因素。而不是吨的 + .swift文件,我保留一个extensions.swift文件,我通常用于每个项目。内部文件的组织方式使得查找扩展的特定类很容易。 – Yohst 2016-02-25 18:15:31

+9

这个答案, + .swift的确是Xcode为Xcode 8中的Core Data创建NSManagedObject子类时的方式。例如:Foo + CoreDataProperties.swift。 – 2016-12-05 20:02:18

+1

如果扩展实现多种方法会怎样? – AlexVPerl 2017-01-29 02:27:53

4

没有Swift约定。保持简单:

StringExtensions.swift 

我为每个我正在扩展的类创建一个文件。如果您为所有扩展使用单个文件,它将很快成为丛林。

+4

这似乎没有特别重用。 – Keller 2016-11-29 21:48:15

+0

相比? – 2016-11-29 23:17:53

+2

与单一(或紧密耦合)的类别扩展文件相比,该文件服务于单一(或明确可关联)的目的。像“StringExtensions”这样的声音听起来像是它可以包含从通用String消毒到应用特定逻辑的所有内容 - 如果重用是一个问题,这可能不是最好的方法。可可命名约定倾向于功能,而不是实现。我认为“StringExtensions”表示后者。除了命名约定之外,我更喜欢被接受的答案,当然在ObjC中,但在Swift中,由于模块的缘故,它似乎是更好的方法。 – Keller 2016-11-30 16:30:23

2

我的首选是将“Extension_”放在文件的开头。 (我把所有相关的扩展插入同一个文件中。)

这样,所有的扩展文件都按照字母顺序排列在我的应用程序目录和Xcode的导航器中。当然,在导航器中,我也可以将它们分组。

因此,一个字符串相关的扩展将进入Extension_String.swift

0

如果你有一个团队商定一套通用和杂项增强功能,它们混为一谈一起作为Extensions.swift工作作为保它,简单的第一级解。但是,随着复杂性的增长,或者扩展变得更加复杂,需要一个层次来封装复杂性。在这种情况下,我会举一个例子来推荐以下做法。

我有一堂课与我的后台谈话,名为Server。它开始扩大以覆盖两个不同的目标应用程序。有些人喜欢一个大文件,但只是逻辑上与扩展分开。我的首选是保持每个文件相对较短,所以我选择了以下解决方案。Server最初符合CloudAdapterProtocol并实施了所有方法。我所做的就是把协议变成一个层次,通过使指下级协议:

protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol { 
    var server: CloudServer { 
     get set 
    } 
    func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) 
} 

Server.swift

import Foundation 
import UIKit 
import Alamofire 
import AlamofireImage 

class Server: CloudAdapterProtocol { 
. 
. 
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) { 
. 
. 
} 

Server.swift然后就实现了设置服务器核心服务器API并获取API版本。真正的工作分为两个文件:

Server_ReggyCloudProtocol.swift 
Server_ProReggyCloudProtocol.swift 

这些实施各自的协议。

这意味着您需要在其他文件中使用导入声明(对于此示例中的Alamofire),但是在我的视图中,对于隔离界面而言,它是一个干净的解决方案。

我认为这种方法与外部指定的类以及您自己的方法同样适用。

0

我更喜欢StringExtensions.swift,直到我添加了太多的东西来将文件拆分为String+utf8Data.swiftString+Encrypt.swift之类的东西。

还有一件事,把类似的文件合并成一个文件会让你的建筑更快。参考Optimizing-Swift-Build-Times