web-dev-qa-db-ja.com

Swift拡張機能:2つのモジュールで同じ拡張機能

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

それらの1つだけをインポートすると、あいまいなエラーはなくなりますが、さらに奇妙なことが起こります。

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

someClassMethod from Swift Foundation

私の質問は、これらの拡張機能(クラス/インスタンスメソッド、プロパティの両方)をあいまいにせずに呼び出すにはどうすればよいですか?できない場合は、Objective-Cで通常行うように、拡張子名にプレフィックスを追加する必要があるということですか?

26
guojiubo

詳細

  • 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 hereenter image description here

あなたの方法

SwiftFoundation.UIView.swiftFoundationSomeClassMethod()

両方のフレームワークのすべてのUIView拡張機能がUIViewクラスに含まれているため、名前空間を使用するバリアントは正しくありません。以下の画像を見ると、SwiftFoundation内にSwiftKitクラスとswiftFoundationSomeClassMethod()があります。これは他の開発者を混乱させる可能性があります。

enter image description here

3

ObjC NSObjectオブジェクトの拡張である場合、例: UIViewの場合、はい、拡張メソッドにはプレフィックスが必要です。

ただし、アンダースコアが見苦しい場合は、Swiftプロトコルを使用して、ここでUIColor.red.my_toImage()UIColor.red.my.toImage()に置き換えるこの代替手段を試すことができます。 より良い管理方法Swiftプロジェクトの拡張機能

1
malhal