Swift扩展:在两个模块中具有相同的扩展功能

Swift扩展:在两个模块中具有相同的扩展功能

问题描述:

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

Say I have a Framework called SwiftKit, which has a UIView's extension class method named someClassMethod and a property named someProperty within it:

// 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:

And I also have a Framework called SwiftFoundation, which also has a UIView's extension class method named someClassMethod and a property named someProperty within it:

// 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()形式的调用:

Then I created a project introduced these Frameworks, things is, if I import both of them in the same swift file and access those extensions, I got a "Ambiguous use of someProperty/someClassMethod()" error, even if I specified the call in the form of 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()'
    }
}

如果仅导入其中一个,则模棱两可的错误消失了,但是发生了更多奇怪的事情:

If I only import one of them, the ambiguous error goes away, but more strange thing happens:

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 Foundation的someProperty

someProperty from Swift Foundation

Swift Foundation的someClassMethod

someClassMethod from Swift Foundation

我的问题是:如何在没有歧义的情况下调用这些扩展(类/实例方法,属性)?如果不能,那是否意味着我们应该像通常使用Objective-C一样在扩展名中添加前缀?

My question is: How can I call these extensions(both class/instance method, properties) without ambiguous? If I cannot, does it mean we should add prefix to extension names as we usually do with Objective-C?

详细信息

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

    • Swift 3, Xcode 8.1
    • Swift 4, Xcode 9.1
    • Swift 5.1, Xcode 11.2.1
    • framework SwiftFoundation和SwiftKit具有相同的属性和函数名称

      frameworks SwiftFoundation and SwiftKit has the same names of the properties and functions

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

      Use different names of the properties and functions

// 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

对属性和功能进行分组

Way2

Group the properties and functions

// 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().这会使其他开发人员感到困惑.

Your variant of using the namespaces is not correct because all UIView extensions from both frameworks are included in you UIView class. Look at image bellow, you can see SwiftKit class and swiftFoundationSomeClassMethod() inside SwiftFoundation. This can confuse other developers.