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的位.这是一个很大的进步.
Eon*_*nil 110
SevenTenEleven在Apple开发论坛上的回答:
命名空间不是每个文件; 它们是每个目标(基于"产品模块名称"构建设置).所以你最终得到这样的东西:
Run Code Online (Sandbox Code Playgroud)import FrameworkA import FrameworkB FrameworkA.foo()所有Swift声明都被认为是某个模块的一部分,因此即使你说"
NSLog"(是的,它仍然存在),你也会得到Swift认为的"Foundation.NSLog".
命名空间隐含在Swift中,所有类(等)都由它们所在的模块(Xcode目标)隐式确定范围.不需要类前缀
似乎与我一直在思考的非常不同.
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
Kev*_*tre 12
我相信这是通过使用:
struct Foo
{
class Bar
{
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用以下方法访问它:
var dds = Foo.Bar();
Run Code Online (Sandbox Code Playgroud)
当您需要定义与现有框架中的类同名的类时,命名空间很有用。
假设您的应用程序具有
MyApp名称,并且您需要声明您的customUICollectionViewController。
您不需要像这样的前缀和子类:
class MAUICollectionViewController: UICollectionViewController {}
Run Code Online (Sandbox Code Playgroud)
像这样做:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Run Code Online (Sandbox Code Playgroud)
为什么?。因为您声明的内容是在当前模块中声明的,这是您当前的目标。并且UICollectionViewControllerfrom UIKit在UIKit模块中声明。
如何在当前模块中使用它?
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)
尽管可以使用框架和库来实现命名空间,但最好的解决方案是使用 Swift Package Manager 来使用本地包。除了具有访问修饰符之外,这种方法还有其他一些好处。与 Swift Package Manager 一样,文件是根据目录系统而不是目标成员身份进行管理的,因此您不必为团队合作中经常出现的合并冲突而烦恼。此外,无需设置文件成员资格。
要检查如何使用本地 Swift 包,请参阅以下链接: 使用本地包组织您的代码