Swiftで名前空間を使用する方法


144

ドキュメントではネストされた型についてのみ言及していますが、それらが名前空間として使用できるかどうかは不明です。名前空間についての明示的な言及は見つかりませんでした。


彼らのiBookをすばやくCtrl-Fで検索すると、名前空間のインスタンスは表示されません...それで、私は何をしていませんか?
Justin Niessner、2014年

1
なぜこの質問が閉じられているのかわかりません。私が見た名前空間を ...スウィフトアイコンの左側に基調に、と私はまだドキュメントからの一切の言及を見つけることができません
eonil

私はこれに関する情報を見つけることができませんでした、Googleは私にこの質問に導きました:)。おそらく、WWDCセッションの1つがこれについてもう少し明らかにするでしょう。
Zyphrax 14年

また、WWDCの誰かが素晴らしい説明をするのを待っています。
eonil 2014年

Eonilの答えは正しいです。Xcodeでモジュールを使用して、クラスを分離します。
Zyphrax 2014年

回答:


113

で答えSevenTenElevenアップルdevのフォーラム

名前空間はファイルごとではありません。それらはターゲットごとです(「製品モジュール名」ビルド設定に基づく)。つまり、次のような結果になります。

import FrameworkA
import FrameworkB

FrameworkA.foo()

すべてのSwift宣言は一部のモジュールの一部と見なされるため、 " NSLog" と言っても(はい、まだ存在します)、Swiftが " Foundation.NSLog" と見なしているものを取得しています。

また、Chris Lattnerが名前空間についてツイートしました

名前空間はSwiftでは暗黙的であり、すべてのクラス(など)は、それらが含まれるモジュール(Xcodeターゲット)によって暗黙的にスコープされます。クラス接頭辞は必要ありません

私が考えていたものとは非常に異なるようです。


6
Apple Devフォーラム...信じられないほどたくさんのタンブルウィードを見てきました。
Nicolas Miari

1
Apple開発forums.developer.apple.comフォーラムへのリンクが壊れており、残念ながらAppleはそのスレッドを新しいフォーラムサイトにインポートしていません。

2
@Daiそれが私たちがQ&AのためにAppleフォーラムを避けるべき理由であるように思われます...しかし、コア開発チームのメンバーはSOをあまり気にしていないようです。なんという悲劇。
2018年

1
タンブルウィードとはどういう意味ですか?
Alexander Mills

148

私はSwiftの名前空間を熱望的だと説明します。地上の意味のある現実に対応しない多くの広告が出されています。

たとえば、WWDCビデオでは、インポートするフレームワークにクラスMyClassがあり、コードにクラスMyClassがある場合、「名前変換」によって異なる内部名が付けられるため、これらの名前は競合しません。ただし、実際には、独自のコードのMyClassが優先されるという意味で、これら競合します。「いいえ、フレームワーク内のMyClassを意味します」と指定することはできません。TheFramework.MyClassいない作業は(コンパイラは、あなたが何を意味するか知っていません、しかしそれはフレームワークでそのようなクラスを見つけることができないと言います)。

私の経験では、Swiftの名前空間はほとんどありません。アプリの1つをObjective-CからSwiftに変える際に、組み込みフレームワークを作成しました。ただし、フレームワークをインポートすると、フレームワーク内のすべてのSwift要素がインポートされます。したがって、やはり、名前空間は1つだけで、それはグローバルです。また、Swiftヘッダーがないため、名前を非表示にすることはできません。

編集:シード3では、この機能が次の意味でオンラインになり始めています:メインコードにMyClassが含まれていて、フレームワークMyFrameworkにMyClassが含まれている場合、前者はデフォルトで後者を上書きしますが、フレームワーク内の1つに到達できます構文を使用してMyFramework.MyClass。したがって、実際には別個の名前空間の基本があります。

編集2:シード4では、アクセス制御を使用できます!加えて、私のアプリの1つに組み込みフレームワークがあり、確かに、すべてがデフォルトで非表示になっていて、パブリックAPIのすべてのビットを明示的に公開する必要がありました。これは大きな改善です。


4
この回答をありがとう。フレームワークだけでなく、標準ライブラリでも機能します。たとえば、配列を「上書き」できます。次に、「配列」は独自のカスタム配列クラスを参照し、標準ライブラリの配列は「Swift.Array」として使用できます。
ジョージ

3
@George NSArrayについても同様です。影を落とした場合でも、として参照できますFoundation.NSArray
2014

1
したがって、ベータ版の名前空間に関する考えの歴史を整理する必要はありません。この答えは今どこにあるのでしょうか。
Dan Rosenstark、2015年

1
編集で述べたとおりの年。モジュール名はあいまいな場合はオプションの名前空間であり、プライバシーが確保されているため、モジュール名は公開されない限り非表示になり、名前をファイルに限定できます。
マット

2
これは長い間私を悩ませてきました。Appleが主張していることから、どのSwiftプロジェクトでもプレフィックスを使用すべきではないようですが、現時点では、アクセス修飾子があってもプレフィックスが必要です。Appleのフレームワークのパッケージクラスまたはプライベートクラスと競合しませんが、Stringなどのパブリックとして宣言されたものは、それをもう一度宣言した場合、または新しいクラスを宣言した場合は、もちろん、自分のクラスを使用することになります。名前空間を使用してすべてのクラスを参照します。
オスカーゴメス

19

これでいくつかの実験をしている間に、ルート「パッケージ」を拡張することにより、自分のファイルにこれらの「名前空間」クラスを作成することになりました。これがベストプラクティスに違反しているかどうか、または私が認識している影響があるかどうかはわかりません(?)

AppDelegate.swift

var n1 = PackageOne.Class(name: "Package 1 class")
var n2 = PackageTwo.Class(name: "Package 2 class")

println("Name 1: \(n1.name)")
println("Name 2: \(n2.name)")

PackageOne.swift

import Foundation

struct PackageOne {
}

PackageTwo.swift

import Foundation

struct PackageTwo {
}

PackageOneClass.swift

extension PackageOne {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

PackageTwoClass.swift

extension PackageTwo {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

編集:

上記のコードで「サブパッケージ」を作成しても、個別のファイルを使用すると機能しないことがわかりました。たぶん誰かがそれが事実である理由についてヒントを与えることができますか?

上記に以下のファイルを追加します。

PackageOneSubPackage.swift

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

PackageOneSubPackageClass.swift

extension PackageOne.SubPackage {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}

そのスローコンパイラエラー: 'SubPackage'は 'PackageOne'のメンバータイプではありません

PackageOneSubPackageClass.swiftからPackageOneSubPackage.swiftにコードを移動すると、機能します。誰でも?

編集2:

これをいじくり回して、パッケージを1つのファイルで定義することにより、パッケージを個別のファイルで拡張できることがわかりました(Xcode 6.1ベータ2で)。

public struct Package {
  public struct SubPackage {
    public struct SubPackageOne {
    }
    public struct SubPackageTwo {
    }
  }
}

ここに要点の私のファイルがあります:https : //gist.github.com/mikajauhonen/d4b3e517122ad6a132b8


興味深い、あなたのテストはどうでしたか?
user2727195 14年

2
「テスト」の意味がわからないが、私は先に進んで上記の手法を使用してアプリを構築し始め、上記のエントリに追加した警告でこれまでのところうまくいくようです。私はそれを他の言語でこのようにコードを編成するのに慣れていたので、それをやっている主な理由は、私が遠くに行くまで、より知識のある人が私に悪い考えを教えてくれるなら感謝します!:)
bWlrYWphdWhvbmVu 2014年

1
続行してください...これは私たちが望んでいることです... 2つの異なるパッケージで同じ名前のクラスを作成し、それに応じて(さらに重要なことに異なるファイルで)存在して参照できるようにし、それが機能しない場合は全体を名前空間のアイデアはフロップのアイデアです...
user2727195

名前空間をハッキングする方法として「構造体」を使用する副作用はありますか?
Alex Nolasco、2014

そのようなパフォーマンスに関して私が遭遇したことではありません。Xcode(6.1 GM)は、まれにタイプが存在しないことを報告する場合がありますが、これもこのようなコードを構造化しない場合に当てはまると思います。私は最近、意味のないすべてのファイルをテストターゲットに追加して1つの問題を解決しましたが、問題は解決しました。:)
bWlrYWphdWhvbmVu 2014年

12

私はこれを使用して達成されていると思います:

struct Foo
{
    class Bar
    {
    }
}

次に、以下を使用してアクセスできます。

var dds = Foo.Bar();

1
名前空間が行われる方法にまだ満足していません...名前空間に10の異なるクラスがある場合、それに加えて、クラスを個別のファイルに保持したい場合は、1つを膨らませたくありませんすべてのクラスのファイル/構造、提案Kevin。
user2727195 2014年

2
彼らがパッケージを含めることを考えなかったのはなぜだろう、それが名前空間ではなく、私たちが必要とするものです。つまり、Java、C#、ActionScriptなどの他の高水準言語を見て、すべてのパッケージがあり、このコンテキストの名前空間はNSを使用することと何も変わりませんまたはプロジェクトクラスの他のプレフィックス
user2727195

1
名前空間をハッキングする方法として構造体を使用すると、未知の問題が発生する可能性があるかどうか疑問に思うことができません。
Alex Nolasco、2014

1
これは良い回避策です。私はこのアプローチを試してみましたが、すぐに止めなければなりませんでした。ビューに関連するクラス(CustomTableViewCellとしましょう)に名前空間を付けようとしたときに、インターフェイスビルダーのオートコンプリートで提案されませんでした。この方法を使用した場合、ビューのクラス名を手動でコピーして貼り付ける必要があります。
ArG、2017年

1
通常はenumでなくを使用するため、をstructインスタンス化することはできませんFoo
ケビン

7

Swiftはpythonのようにモジュールを使用し(ここここを参照)、@ Kevin Sylvestreが示唆したように、ネストされた型を使用することもできますを名前空間としてます。

そして、@ Daniel A. Whiteからの回答を拡張するために、WWDCでは、彼らはモジュールについて迅速に話していました。

また、ここでは説明されています:

推論された型はコードをより簡潔にし、間違いを起こしにくくしますが、モジュールはヘッダーを排除して名前空間を提供します。


2
2番目のリンク6.4 Packages(Python)で述べたように、コンストラクトのようなパッケージを探しています。ネストされた型はそれほど遠くに行けないので、名前空間は10の異なるクラスと名前空間の異なるファイルにある場合、またはパッケージ???
user2727195 2014年

7
  • 名前空間は、同じでクラスを定義する必要がある場合に役立ちます、既存のフレームワークでクラス名前の。

  • アプリにMyApp名前があり、カスタムを宣言する必要があるとしますUICollectionViewController

次のようにプレフィックスとサブクラスを付ける必要はありません

class MAUICollectionViewController: UICollectionViewController {}

このようにしてください:

class UICollectionViewController {} //no error "invalid redeclaration o..."

どうして?。あなたが宣言したものは、現在のターゲットである現在のモジュールで宣言されているからです。そしてから宣言されているUICollectionViewControllerUIKitUIKitモジュールます。

現在のモジュール内でどのように使用しますか?

var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

それらを別のモジュールと区別する方法は?

var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit

3

extensionを使用すると、structすべてのコードを右にインデントすることなく、前述のsアプローチを名前空間に使用できます。私はこれを少しいじっていましたが、私が作成しControllersViews、以下の例のように名前空間まで行くかどうかはわかりませんが、それがどこまでできるかを示しています:

Profiles.swift

// Define the namespaces
struct Profiles {
  struct Views {}
  struct ViewControllers {}
}

プロファイル/ViewControllers/Edit.swift

// Define your new class within its namespace
extension Profiles.ViewControllers {
  class Edit: UIViewController {}
}

// Extend your new class to avoid the extra whitespace on the left
extension Profiles.ViewControllers.Edit {
  override func viewDidLoad() {
    // Do some stuff
  }
}

プロファイル/ビュー/Edit.swift

extension Profiles.Views {
  class Edit: UIView {}
}

extension Profiles.Views.Edit {
  override func drawRect(rect: CGRect) {
    // Do some stuff
  }
}

このレベルの分離はまだ必要ないので、これをアプリで使用していませんが、興味深いアイデアだと思います。これにより、ユビキタスな* ViewControllerサフィックスなど、煩わしいほど長いクラスサフィックスも不要になります。

ただし、次のようなメソッドパラメータなどで参照されている場合は、何も短縮されません。

class MyClass {
  func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
    // secret sauce
  }
}

2

2014年6月10日現在、誰かが興味を持っている場合、これはSwiftの既知のバグです。

セブンテンイレブンから

「既知のバグ、申し訳ありません。rdar:// problem / 17127940モジュール名によるSwiftタイプの修飾は機能しません。」


以下の@mattの投稿によると、これは現在Swiftの既知のバグです。
Adam Venturella 14

これは現在ベータ3で修正されています(2014年7月7日リリース)
Adam Venturella 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.