如何在Swift中使用命名空间?
文档只提到了嵌套types,但不清楚它们是否可以用作名称空间。 我还没有发现任何明确提及的命名空间。
在Apple开发论坛中由SevenTenEleven回答:
命名空间不是每个文件; 他们是每个目标(根据“产品模块名称”版本设置)。 所以你最终会得到这样的东西:
import FrameworkA import FrameworkB FrameworkA.foo()
所有的Swift声明都被认为是某个模块的一部分,所以即使你说“
NSLog
”(是的,它仍然存在),你会得到Swift认为的“Foundation.NSLog
”。
另外Chris Lattner在 Twitter上发布了关于命名空间的推文 。
命名空间在Swift中是隐含的,所有的类(等)都被它们所在的模块(XCode目标)隐式地限定范围。不需要类前缀
似乎和我一直在想的很不一样。
我会把Swift的命名空间描述为理想; 它被给了很多广告,不符合任何有意义的现实。
例如,WWDCvideo指出,如果您要导入的框架具有MyClass类,并且您的代码具有MyClass类,则这些名称不会相互冲突,因为“name mangling”为它们提供了不同的内部名称。 但是,实际上,它们会发生冲突,就是说你自己的代码的MyClass会赢,而你不能指定“No no,我的意思是框架中的MyClass” – 说TheFramework.MyClass
不起作用(编译器知道你是什么意思,但它说在框架中找不到这样的类)。
我的经验是,斯威夫特因此丝毫没有命名空间。 在将我的一个应用程序从Objective-C转换到Swift时,我创build了一个embedded式框架,因为它非常容易和很酷。 但是,导入框架会导入框架中的所有Swift东西 – 所以,再一次,只有一个名称空间,它是全局的。 而且没有Swift头文件,所以你不能隐藏任何名字。
编辑:在种子3,这个function现在开始联机,在以下意义上:如果您的主代码包含MyClass和您的框架MyFramework包含MyClass,前者默认情况下掩盖后者,但你可以达到在框架通过使用语法MyFramework.MyClass
。 因此,我们确实有一个独特的命名空间的雏形!
编辑2:在种子4,我们现在有访问控制! 另外,在我的一个应用程序中,我有一个embedded式框架,当然,默认情况下,所有东西都是隐藏的,我必须明确公开所有的API。 这是一个很大的改进。
在对此进行一些实验的时候,我最终通过扩展根“package”来在自己的文件中创build这些“命名空间”类。 不知道这是否违背最佳实践,或者如果它有我意识到的任何影响(?)
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 } } }
编辑:
刚刚发现,在上面的代码中创build“子包”不会工作,如果使用单独的文件。 也许有人可以暗示为什么会这样?
将以下文件添加到上面:
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”的成员types
如果我将代码从PackageOneSubPackageClass.swift移动到PackageOneSubPackage.swift,它就可以工作。 任何人?
编辑2:
摆弄这个仍然发现(在Xcode 6.1testing版2),通过定义在一个文件中的包,他们可以扩展在单独的文件:
public struct Package { public struct SubPackage { public struct SubPackageOne { } public struct SubPackageTwo { } } }
以下是我的档案: https : //gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
我相信这是通过使用:
struct Foo { class Bar { } }
然后可以使用以下方式访问它:
var dds = Foo.Bar();
Swift很像Python中使用模块(参见这里和这里 ),而@Kevin Sylvestrebuild议你也可以使用嵌套types作为名称空间。
为了扩展来自@Daniel A. White的答案,他们在WWDC上迅速地讨论了这些模块。
另外在这里解释:
推断types使代码更清晰,不易出错,而模块消除标题并提供名称空间。
如果有人好奇,截至2014年6月10日,这是Swift中的一个已知错误:
从SevenTenEleven
“已知的错误,对不起! rdar://问题/ 17127940通过模块名称来限定 Swifttypes不起作用。”
命名空间在需要在现有框架中定义与类名相同的类时非常有用。
假设您的应用程序具有
MyApp
名称,并且您需要声明您的自定义UICollectionViewController
。
你不需要这样的前缀和子类:
class MAUICollectionViewController: UICollectionViewController {}
像这样做:
class UICollectionViewController {} //no error "invalid redeclaration o..."
为什么? 。 因为你声明的是在当前模块中声明的,这是你当前的目标 。 UIKit
UICollectionViewController
在UIKit
模块中声明。
如何在当前模块中使用它?
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
你可以使用extension
来为命名空间使用上面提到的struct
方法,而不必将所有的代码缩进到右边。 我一直在玩弄这一点,我不知道我会尽可能创buildControllers
和Views
命名空间,如下面的例子,但它确实说明了它可以走多远:
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 } }
- IOS7中的状态栏和导航栏问题
- 子类化时混合了objective-c和swift
- CLLocationManager startUpdatingLocation不调用locationManager:didUpdateLocations:或locationManager:didFailWithError:
- 尝试加载视图控制器的视图,而它正在释放… UISearchController
- 如何closures在Swift ViewController?
- 什么时候应该在Xcode中使用“embedded式二进制文件”而不是“链接的框架”?
- 使用Objective C读取发布到设备控制台的日志消息
- 最简单的方法来检测捏
- iPhone – 知道如果UIScrollView达到顶部或底部