Swift 扩展最佳实践

Posted

技术标签:

【中文标题】Swift 扩展最佳实践【英文标题】:Swift Extensions Best Practices 【发布时间】:2016-10-09 19:07:19 【问题描述】:

我最近沉迷于Extensions。我发现是一个巨大的 PITA 的一件事是弄清楚我在哪里存放了一个有用的方法,例如 ArrayNSManagedObject 等。

我所做的是将我的扩展名放在一个名为 CustomExtensionsNSObject 类文件中,并按字母顺序列出类扩展名。

它有效,但我想看看它是否符合最佳实践。如果没有,跟踪Extensions 的最佳方式是什么?

这是我所做的:

class CustomExtensions: NSObject 
    /*
     Useful extensions, nothing else here
     */

// Example extension    
extension Int 
    func formatAsTimeString() -> String 
        let seconds = self % 60
        let minutes = (self / 60) % 60
        let hours = self / 3600
        let stringHours = hours > 9 ? String(hours) : "0" + String(hours)
        let stringMinutes = minutes > 9 ? String(minutes) : "0" + String(minutes)
        let stringSeconds = seconds > 9 ? String(seconds) : "0" + String(seconds)

        if hours > 0 
            return "\(stringHours):\(stringMinutes):\(stringSeconds)"
        
        else 
            return "\(stringMinutes):\(stringSeconds)"
        
    

// More extensions below

【问题讨论】:

你把你的扩展放入NSObject是什么意思? Array 扩展名不应任何其他类中,例如... @DanielT。谢谢阅读。我更新了我的答案,这样你就可以看到我做了什么。 根据您的示例,我仍然不明白这个 CustomExtensions 类应该用于什么。你肯定不会从它中分出子类,是吗? 我刚刚创建了一个空白的NSObject 类并将扩展名放在它的底部,这样它们就都在一个地方,而不是分散在一堆不同的文件中。这种方法对我有用,但我想看看它是否符合最佳做法。 如果CustomExtensions 类为空,则将其删除。这是完全没有必要的。我现在正在为您的问题撰写答案... 【参考方案1】:

我认为围绕这​​个问题的“最佳做法”尚未找到。也就是说,这里是 MHO:

最终,我对待这些扩展的方式与我在 C 中处理全局函数的方式相同。毕竟,它们基本上就是这样。具有特殊语法的全局函数...

如果扩展名只在一个文件中使用,那么我会将扩展名放在同一个文件中。当我完成时,我最终得到了很多这样的东西。例如,您的 formatAsTimeString 是一种视图模型。如果它由单个视图控制器使用,我会将其保留在视图控制器的文件中。

如果扩展名被多个类使用,那么我会将它分解为一个单独的文件。我将在扩展名后命名文件。因此,例如,如果formatAsTimeString 在多个文件中使用,那么我将有一个名为“Int+formatAsTimeString.swift”的文件,扩展名可以在其中存在。

如果有很多相关的函数,那么我会将它们放在同一个文件中,并根据函数的抽象思想来命名文件。我通过想象如果我选择在不同的程序中使用它们是否必须一起移动它们来决定这些函数是相关的......例如,也许我还有其他时间字符串相关的函数......

【讨论】:

很棒的想法。我开始使用这种方法在应用程序中检索UserDefault 值,然后我开始在其中扔其他东西。在我以这种方式做事之前,我想得到一些输入。感谢您周到的回答。【参考方案2】:

对于 Swift3,如果扩展名仅用于一个文件,我通常倾向于使用“fileprivate”。

fileprivate extension Date

    func toString( dateFormat format  : String ) -> String
    
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = format
        return dateFormatter.string(from: self)
    

【讨论】:

【参考方案3】:

我希望对此有良好的“官方”指南!但正如我们所提到的,人们正在解决这个问题。

ViewController-扩展

我发现一个有趣的用途是更复杂的类的文件内扩展,例如 ViewController。

而不是去:

public class MainViewController: UIViewController, SpecialDelegate 
  // functions

您可以将每个导入分散到其自己的扩展中:

public class MainViewController: UIViewController 
  // functions


extension MainViewController: SpecialDelegate 
  // functions

这些有效地用作更简单的格式,并且可以更容易地组织扩展类,尤其是对于非常大的类/项目。请注意,这些应该保留在同一个文件中,或者至少在主文件旁边的文件中。

简单的附加功能

对于像这样的简单扩展:

extension Int 
  /**
   Returns true when the integer is even.
   */
  var isEven: Bool 
    return self % 2 == 0
  

我通常有一个标记为extensions 的文件夹,其中保存了所有扩展文件。我见过更复杂的项目,文件更接近它们的使用位置,但我不同意这种用法。

毕竟,扩展应该在整个项目中使用,隐藏它们会使查找某个扩展是否已经存在变得更加困难。

高度专业化的功能

正如这里其他回复中提到的,为不会在其他地方使用的用例创建一个文件私有扩展名并放入使用它的文件中是有意义的

fileprivate extension String 
  // Highly specialized function that will NEVER be used anywhere else

扩展命名

我注意到各种类型的写出扩展文件。当我开始做 ios 开发时,流行的指导方针是写 String-Extension.swift。如今String+Extension.swift 似乎赢了。

除此之外,很多人将添加的功能的名称写入文件,例如Int+IsEven.swift,但这只有在每个文件只有一个功能时才有用。

【讨论】:

以上是关于Swift 扩展最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中全局变量和函数的最佳实践是啥?

Firebase swift tabBarController 最佳实践

iOS开发入门——17条 Swift 最佳实践规范(下)

在 Swift 中验证电子邮件地址的最佳实践是啥?

同步数组(针对喜欢/关注者)最佳实践 [Firebase Swift]

iOS开发入门——17条 Swift 最佳实践规范(上)