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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24002821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 00:15:53  来源:igfitidea点击:

How to use Namespaces in Swift?

iosmacosswift

提问by lassej

The documentation only mentions nested types, but it's not clear if they can be used as namespaces. I haven't found any explicit mentioning of namespaces.

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

采纳答案by Eonil

Answered by SevenTenElevenin the Apple dev forum:

SevenTenElevenApple 开发论坛中的回答:

Namespaces are not per-file; they're per-target (based on the "Product Module Name" build setting). So you'd end up with something like this:

import FrameworkA
import FrameworkB

FrameworkA.foo()

All Swift declarations are considered to be part of some module, so even when you say "NSLog" (yes, it still exists) you're getting what Swift thinks of as "Foundation.NSLog".

命名空间不是每个文件;它们是针对每个目标的(基于“产品模块名称”构建设置)。所以你最终会得到这样的结果:

import FrameworkA
import FrameworkB

FrameworkA.foo()

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

Also Chris Lattnertweeted about namespacing.

此外克里斯·拉特纳啾啾关于命名空间

Namespacing is implicit in Swift, all classes (etc) are implicitly scoped by the module (Xcode target) they are in. no class prefixes needed

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

Seems to be very different what I have been thinking.

似乎和我一直在想的很不一样。

回答by matt

I would describe Swift's namespacing as aspirational; it's been given a lot of advertising that doesn't correspond to any meaningful reality on the ground.

我会将 Swift 的命名空间描述为有抱负;它被给予了很多与当地任何有意义的现实不符的广告。

For example, the WWDC videos state that if a framework you're importing has a class MyClass and your code has a class MyClass, those names do not conflict because "name mangling" gives them different internal names. In reality, however, they doconflict, in the sense that your own code's MyClass wins, and you can't specify "No no, I mean the MyClass in the framework" — saying TheFramework.MyClassdoesn't work (the compiler knows what you mean, but it says it can't find such a class in the framework).

例如,WWDC 视频指出,如果您要导入的框架具有类 MyClass 并且您的代码具有类 MyClass,则这些名称不会冲突,因为“名称修改”为它们提供了不同的内部名称。然而,实际上,它们确实存在冲突,因为您自己的代码的 MyClass 获胜,并且您不能指定“不不,我指的是框架中的 MyClass”——说TheFramework.MyClass不起作用(编译器知道您的意思) ,但它说它在框架中找不到这样的类)。

My experience is that Swift therefore is not namespaced in the slightest. In turning one of my apps from Objective-C to Swift, I created an embedded framework because it was so easy and cool to do. Importing the framework, however, imports all the Swift stuff in the framework - so presto, once again there is just one namespace and it's global. And there are no Swift headers so you can't hide any names.

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

EDIT:In seed 3, this feature is now starting to come online, in the following sense: if your main code contains MyClass and your framework MyFramework contains MyClass, the former overshadows the latter by default, but you can reach the one in the framework by using the syntax MyFramework.MyClass. Thus we do in fact have the rudiments of a distinct namespace!

编辑:在种子 3 中,此功能现在开始上线,从以下意义上说:如果您的主代码包含 MyClass,而您的框架 MyFramework 包含 MyClass,则默认情况下前者会掩盖后者,但您可以到达框架中的那个通过使用语法MyFramework.MyClass。因此,我们实际上确实拥有不同命名空间的基本要素!

EDIT 2:In seed 4, we now have access controls! Plus, in one of my apps I have an embedded framework and sure enough, everything was hidden by default and I had to expose all the bits of the public API explicitly. This is a big improvement.

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

回答by bWlrYWphdWhvbmVu

While doing some experimentation with this I ended up creating these "namespaced" classes in their own files by extending the root "package". Not sure if this is against best practices or if it has any implications I'm mot aware of(?)

在对此进行一些实验时,我最终通过扩展根“包”在它们自己的文件中创建了这些“命名空间”类。不确定这是否违反最佳实践,或者它是否有任何我不知道的影响(?)

AppDelegate.swift

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

PackageOne.swift

import Foundation

struct PackageOne {
}

PackageTwo.swift

PackageTwo.swift

import Foundation

struct PackageTwo {
}

PackageOneClass.swift

PackageOneClass.swift

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

PackageTwoClass.swift

PackageTwoClass.swift

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


Edit:

编辑:

Just found out that creating "subpackages" in above code wont work if using separate files. Maybe someone can hint on why that would be the case?

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

Adding following files to the above:

在上面添加以下文件:

PackageOneSubPackage.swift

PackageOneSubPackage.swift

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

PackageOneSubPackageClass.swift

PackageOneSubPackageClass.swift

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

Its throwing a compiler error: 'SubPackage' is not a member type of 'PackageOne'

它抛出一个编译器错误:“SubPackage”不是“PackageOne”的成员类型

If I move the code from PackageOneSubPackageClass.swift to PackageOneSubPackage.swift it works. Anyone?

如果我将代码从 PackageOneSubPackageClass.swift 移动到 PackageOneSubPackage.swift 它将起作用。任何人?

Edit 2:

编辑2:

Fiddling around with this still and found out (in Xcode 6.1 beta 2) that by defining the packages in one file they can be extended in separate files:

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

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

Here are my files in a gist: https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8

这是我的文件要点:https: //gist.github.com/mikajauhonen/d4b3e517122ad6a132b8

回答by Kevin Sylvestre

I believe this is achieved using:

我相信这是使用以下方法实现的:

struct Foo
{
    class Bar
    {
    }
}

Then it can be accessed using:

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

var dds = Foo.Bar();

回答by Ivan Genchev

Swift uses modules much like in python (see hereand here) and as @Kevin Sylvestre suggested you can also use the nested typesas namespaces.

Swift 使用的模块与 Python 中的非常相似(参见此处此处),并且正如 @Kevin Sylvestre 所建议的,您也可以将嵌套类型用作命名空间。

And to extend the answer from @Daniel A. White, in WWDC they were talking about the modules in swift.

为了扩展@Daniel A. White 的回答,他们在 WWDC 中讨论了 swift 中的模块。

Also hereis explained:

此外在这里解释:

Inferred types make code cleaner and less prone to mistakes, while modules eliminate headers and provide namespaces.

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

回答by Bart?omiej Semańczyk

  • Namespaces are useful when you need to define class with the samename as class in existing framework.

  • Suppose your app has MyAppname, and you need to declare your custom UICollectionViewController.

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

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

You don't needto prefix and subclass like this:

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

class MAUICollectionViewController: UICollectionViewController {}

Do it like this:

像这样做:

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

Why?. Because what you've declared is declared in current module, which is your current target. And UICollectionViewControllerfrom UIKitis declared in UIKitmodule.

为什么?. 因为您声明的内容是在current module 中声明的,也就是您当前的 target。并且UICollectionViewControllerfromUIKitUIKit模块中声明。

How to use it within current module?

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

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

How to distinguish them from another module?

如何将它们与其他模块区分开来?

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

回答by Sebastien Martin

You can use extensionto use the mentioned structs approach for namespacing without having to indent all of your code towards the right. I've been toying with this a bit and I'm not sure I'd go as far as creating Controllersand Viewsnamespaces like in the example below, but it does illustrate how far it can go:

您可以使用extension提到的structs 方法进行命名空间,而不必向右缩进所有代码。我一直在玩这个,我不确定我会像下面的例子那样创建ControllersViews命名空间,但它确实说明了它可以走多远:

Profiles.swift:

Profiles.swift

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

Profiles/ViewControllers/Edit.swift

配置文件/视图控制器/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
  }
}

Profiles/Views/Edit.swift

个人资料/视图/Edit.swift

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

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

I haven't used this in an app since I haven't needed this level of separation yet but I think it's an interesting idea. This removes the need for even class suffixes such as the ubiquitous *ViewController suffix which is annoyingly long.

我还没有在应用程序中使用它,因为我还不需要这种级别的分离,但我认为这是一个有趣的想法。这消除了对偶数类后缀的需要,例如无处不在的 *ViewController 后缀,它非常长。

However, it doesn't shorten anything when it's referenced such as in method parameters like this:

但是,当它被引用时,它不会缩短任何东西,例如在这样的方法参数中:

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

回答by Adam Venturella

In case anyone was curious, as of June 10th 2014, this is a known bug in Swift:

如果有人好奇,截至 2014 年 6 月 10 日,这是 Swift 中的一个已知错误:

From SevenTenEleven

来自7111

"Known bug, sorry! rdar://problem/17127940Qualifying Swift types by their module name doesn't work."

“已知错误,抱歉!rdar://problem/17127940通过模块名称限定Swift 类型不起作用。”