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

时间:2015-09-23 10:08:48

标签: swift namespaces swift-extensions

假设我有一个名为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的框架,它还有一个名为someClassMethod的UIView扩展类方法和一个名为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 Foundation的

someProperty

     

来自Swift Foundation的someClassMethod

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

2 个答案:

答案 0 :(得分:3)

详细

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

问题

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

决定

WAY1

使用不同的属性和功能名称

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

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

Way2

对属性和功能进行分组

// 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()
    }
}

项目

enter image description here enter image description here

您的方法

SwiftFoundation.UIView.swiftFoundationSomeClassMethod()

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

enter image description here

答案 1 :(得分:0)

如果它是NSObject之类的ObjC UIView对象的扩展,则是,扩展方法需要前缀。

但是对于那些发现下划线不雅观的人可以使用此方法,这是一种使用Swift协议将UIColor.red.my_toImage()替换为UIColor.red.my.toImage()的替代技术,请点击此处Better way to manage swift extensions in your project

详细了解