如何在Swift中使用命名空间?

las*_*sej 139 macos ios swift

该文档仅提到嵌套类型,但不清楚它们是否可以用作命名空间.我没有发现任何明确提到的命名空间.

mat*_*att 146

我会把斯威夫特的名字空间描述为有抱负的; 它被广泛宣传,与当地任何有意义的现实都不相符.

例如,WWDC视频声明如果您导入的框架具有类MyClass并且您的代码具有类MyClass,则这些名称不会发生冲突,因为"名称修改"会为它们提供不同的内部名称.但在现实中,他们做的冲突,在你自己的代码的MyClass的胜利感,你不能指定"不,不,我的意思是在框架中的MyClass的" -他说TheFramework.MyClass不行(编译器知道你是什么意思,但它说它在框架中找不到这样的类).

我的经验是,Swift因此没有一点点命名空间.在将我的一个应用程序从Objective-C转换为Swift之后,我创建了一个嵌入式框架,因为它非常简单和酷.然而,导入框架会导入框架中的所有Swift内容 - 所以,再次只有一个名称空间,它是全局的.并且没有Swift标头,因此您无法隐藏任何名称.

编辑:在种子3,这个功能现在开始联机,在下面的意义:如果你的主代码包含MyClass的和你的框架MyFramework包含MyClass的,前者掩盖后者默认,但你可以达到一个在框架通过使用语法MyFramework.MyClass.因此,我们确实拥有一个独特命名空间的雏形!

编辑2:在种子4中,我们现在有访问控制!另外,在我的一个应用程序中,我有一个嵌入式框架,当然,默认情况下一切都是隐藏的,我必须明确公开所有公共API的位.这是一个很大的进步.

  • +1"编辑"更新.谢谢 (45认同)
  • 谢谢你的回答.它不仅适用于Frameworks,还适用于标准库.例如,您可以"覆盖"数组.然后"Array"指的是您自己的自定义Array类,Standard Library的Array可用作"Swift.Array". (4认同)
  • @George同样适用于NSArray; 如果你黯然失色,你仍然可以称之为"Foundation.NSArray". (3认同)
  • 这一直困扰着我很长一段时间,似乎任何Swift项目都不应该使用前缀,因为Apple声称这样做,但是此时仍需要前缀,即使使用访问修饰符也是如此.虽然你不会与Apple的框架中的包或私有类发生冲突,但是任何声明为public的东西,例如String,如果再次声明,或者任何新的类,它最终会使用你的,除非你习惯于引用所有具有命名空间的类....不好的imo. (2认同)

Eon*_*nil 110

SevenTenElevenApple开发论坛上的回答:

命名空间不是每个文件; 它们是每个目标(基于"产品模块名称"构建设置).所以你最终得到这样的东西:

import FrameworkA
import FrameworkB

FrameworkA.foo()
Run Code Online (Sandbox Code Playgroud)

所有Swift声明都被认为是某个模块的一部分,因此即使你说" NSLog"(是的,它仍然存在),你也会得到Swift认为的" Foundation.NSLog".

克里斯拉特纳也发布了关于命名空间的推文.

命名空间隐含在Swift中,所有类(等)都由它们所在的模块(Xcode目标)隐式确定范围.不需要类前缀

似乎与我一直在思考的非常不同.

  • Apple Dev论坛......我见过那么多你不相信的风滚草! (5认同)
  • @Dai似乎这就是为什么我们应该避免Apple论坛进行Q&A ......但核心开发团队成员似乎并不关心SO.真是个悲剧. (2认同)
  • @AlexanderMills 我知道这是四年多后的事了,来回答你的问题:想象一下你在电影中看到的一个古老的西部小镇,它是空的,你看到没有人,只有风滚草吹过街道。 (2认同)

bWl*_*mVu 18

在对此进行一些实验时,我最终通过扩展根"package"在自己的文件中创建这些"命名空间"类.不确定这是否违反最佳做法或是否有任何影响我很清楚(?)

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)")
Run Code Online (Sandbox Code Playgroud)

PackageOne.swift

import Foundation

struct PackageOne {
}
Run Code Online (Sandbox Code Playgroud)

PackageTwo.swift

import Foundation

struct PackageTwo {
}
Run Code Online (Sandbox Code Playgroud)

PackageOneClass.swift

extension PackageOne {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PackageTwoClass.swift

extension PackageTwo {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

刚刚发现,如果使用单独的文件,在上面的代码中创建"子包"将无法工作.也许有人可以暗示为什么会这样?

将以下文件添加到上面:

PackageOneSubPackage.swift

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}
Run Code Online (Sandbox Code Playgroud)

PackageOneSubPackageClass.swift

extension PackageOne.SubPackage {
    class Class {
        var name: String
        init(name:String) {
            self.name = name
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出编译错误:'SubPackage'不是'PackageOne'的成员类型

如果我将代码从PackageOneSubPackageClass.swift移动到PackageOneSubPackage.swift它可以工作.任何人?

编辑2:

摆弄这个仍然发现(在Xcode 6.1 beta 2中)通过在一个文件中定义包,它们可以在单独的文件中扩展:

public struct Package {
  public struct SubPackage {
    public struct SubPackageOne {
    }
    public struct SubPackageTwo {
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是我在gist中的文件:https: //gist.github.com/mikajauhonen/d4b3e517122ad6a132b8

  • 不确定你的"测试"是什么意思,但我继续使用上述技术开始构建我的应用程序,到目前为止似乎运行良好,我在上面的条目中添加了警告.我这样做主要是因为我习惯用其他语言以这种方式组织我的代码,如果任何有更多知识的人在我走得太远之前能告诉我一个坏主意,我将不胜感激!:) (2认同)
  • 使用“struct”作为破解命名空间的方法有副作用吗? (2认同)

Kev*_*tre 12

我相信这是通过使用:

struct Foo
{
    class Bar
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以使用以下方法访问它:

var dds = Foo.Bar();
Run Code Online (Sandbox Code Playgroud)

  • 我想知道为什么他们不考虑包括我们需要的包,而不是命名空间,我的意思是看其他高级语言,如Java,C#,ActionScript,它们都有包,这个上下文中的命名空间与使用NS没什么不同或项目类的其他前缀 (2认同)
  • 不禁想知道使用结构作为破解命名空间的方法是否会导致未知问题。 (2认同)

Iva*_*hev 7

Swift使用类似于python的模块(参见此处此处),并且@Kevin Sylvestre建议您也可以使用嵌套类型作为命名空间.

为了扩展@Daniel A. White的答案,在WWDC中他们正在谈论swift中的模块.

此外在这里解释:

推断类型使代码更清晰,更不容易出错,而模块则消除标头并提供名称空间.

  • 我正在寻找像你的第二个链接上提到的类似的包6.4包(Python),作为嵌套类型的命名空间不能走得太远,如果我有10个不同的类和命名空间中的不同文件,或者让我们说一个包??? (2认同)

Bar*_*zyk 5

  • 当您需要定义与现有框架中的类同名的类时,命名空间很有用。

  • 假设您的应用程序具有MyApp名称,并且您需要声明您的custom UICollectionViewController

不需要像这样的前缀和子类:

class MAUICollectionViewController: UICollectionViewController {}
Run Code Online (Sandbox Code Playgroud)

像这样做:

class UICollectionViewController {} //no error "invalid redeclaration o..."
Run Code Online (Sandbox Code Playgroud)

为什么?。因为您声明的内容是在当前模块中声明的,这是您当前的目标。并且UICollectionViewControllerfrom UIKitUIKit模块中声明。

如何在当前模块中使用它?

var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Run Code Online (Sandbox Code Playgroud)

如何将它们与另一个模块区分开?

var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Run Code Online (Sandbox Code Playgroud)


Ami*_*eza 2

尽管可以使用框架和库来实现命名空间,但最好的解决方案是使用 Swift Package Manager 来使用本地包。除了具有访问修饰符之外,这种方法还有其他一些好处。与 Swift Package Manager 一样,文件是根据目录系统而不是目标成员身份进行管理的,因此您不必为团队合作中经常出现的合并冲突而烦恼。此外,无需设置文件成员资格。

要检查如何使用本地 Swift 包,请参阅以下链接: 使用本地包组织您的代码