【问题标题】:Swift Extension: same extension function in two ModulesSwift 扩展:两个模块中的相同扩展功能
【发布时间】:2015-12-20 14:26:08
【问题描述】:

假设我有一个名为 SwiftKit 的框架,它有一个名为 someClassMethod 的 UIView 扩展类方法和一个名为 someProperty 的属性:

// SwiftKit
public extension UIView {
    class func someClassMethod() {
        print("someClassMethod from Swift Kit")
    }

    var someProperty: Double {
        print("someProperty from Swift Kit")
        return 0
    }
}

我还有一个叫 SwiftFoundation 的框架,它里面还有一个 UIView 的扩展类方法叫 someClassMethod 和一个叫 someProperty 的属性:

// SwiftFoundation
public extension UIView {
    class func someClassMethod() {
        print("someClassMethod from Swift Foundation")
    }

    var someProperty: Double {
        print("someProperty from Swift Foundation")
        return 0
    }
}

然后我创建了一个项目来介绍这些框架,事情是,如果我将它们都导入同一个 swift 文件并访问这些扩展,我得到一个“模糊使用 someProperty/someClassMethod()”错误,即使我指定SwiftKit.UIView.someClassMethod() 形式的调用:

import UIKit
import SwiftKit
import SwiftFoundation

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.view.someProperty              // error: Ambiguous use of 'somProperty'
        SwiftKit.UIView.someClassMethod()   // error: Ambiguous use of 'someClassMethod()'
    }
}

如果我只导入其中一个,模棱两可的错误就会消失,但会发生更奇怪的事情:

import UIKit
import SwiftKit
//import SwiftFoundation

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.view.someProperty
        SwiftKit.UIView.someClassMethod()
    }
}

控制台打印出来:

来自 Swift 基金会的 someProperty

来自 Swift Foundation 的 someClassMethod

我的问题是:我如何才能毫不含糊地调用这些扩展(类/实例方法、属性)?如果不能,是否意味着我们应该像通常使用 Objective-C 一样为扩展名添加前缀?

【问题讨论】:

  • 我假设 ModuleA.UIColor.randomColor() 有效(假设您将其定义为 类方法)。你试过了吗?
  • 我刚刚检查了一个类似的扩展,Module.UIColor.myCustomColor() 编译得很好。
  • @MartinR 感谢您的回复,我已经把问题说得更清楚了,非常感谢您的进一步帮助。
  • 我的假设(我自己没有测试过):它应该适用于纯 Swift 类,但不适用于从 NSObject 继承的类,因为在不同的类类别中定义相同的方法在 Objective 中是未定义的行为-C.
  • 我可以建议清理和构建吗?

标签: swift namespaces swift-extensions


【解决方案1】:

详情

  • Swift 3,Xcode 8.1
  • Swift 4,Xcode 9.1
  • Swift 5.1,Xcode 11.2.1

问题

框架 SwiftFoundation 和 SwiftKit 具有相同名称的属性和函数

决定

方式1

使用不同的属性和函数名称

// SwiftFoundation
public extension UIView {
    public class func swiftFoundationSomeClassMethod() {
        print("someClassMethod from Swift Foundation")
    }

    public var swiftFoundationSomeProperty: Double {
        print("someProperty from Swift Foundation")
        return 0
    }
}

方式2

对属性和函数进行分组

// SwiftKit
public extension UIView {
    public class SwiftKit {
        public class func someClassMethod() {
            print("someClassMethod from Swift Kit")
        }

        public var someProperty: Double {
            print("someProperty from Swift Kit")
            return 0
        }
    }

    var SwiftKit: SwiftKit { return SwiftKit() }
}

结果

import UIKit
import SwiftKit
import SwiftFoundation

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        _ = view.SwiftKit.someProperty
        UIView.SwiftKit.someClassMethod()

        _ = view.swiftFoundationSomeProperty
        UIView.swiftFoundationSomeClassMethod()
    }
}

项目

你的方法

SwiftFoundation.UIView.swiftFoundationSomeClassMethod()

您使用命名空间的变体不正确,因为这两个框架的所有 UIView 扩展都包含在您的 UIView 类中。查看下图,您可以在 SwiftFoundation 中看到 SwiftKit 类和 swiftFoundationSomeClassMethod()。这可能会使其他开发人员感到困惑。

【讨论】:

    【解决方案2】:

    如果它是 ObjC NSObject 对象的扩展,例如UIView,那么是的,扩展方法需要一个前缀。

    但是,那些认为下划线难看的人可以尝试使用 Swift 协议将 UIColor.red.my_toImage() 替换为 UIColor.red.my.toImage() 的替代方法:Better way to manage swift extensions in your project

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2022-01-09
      相关资源
      最近更新 更多