159

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.

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
lassej
  • 6,256
  • 6
  • 26
  • 34
  • A quick Ctrl-F search of their iBook shows no instances of namespaces...so I'm going with no? – Justin Niessner Jun 02 '14 at 20:39
  • 1
    I don't know why this question is closed. I saw **namespace** on keynote at the left side of Swift icon, and I still cannot find any mention from the documentation... – eonil Jun 03 '14 at 05:26
  • I couldn't find any information on this, Google led me to this question :). Perhaps one of the WWDC sessions will shed a bit more light on this. – Yvo Jun 03 '14 at 07:53
  • I am also waiting for someone in WWDC to come up with nice explanation. – eonil Jun 04 '14 at 07:56
  • Eonil's answer is correct. You use modules in Xcode to separate your classes. – Yvo Jun 05 '14 at 06:45
  • You can actually use the "enum" trick: https://cocoacasts.com/namespaces-in-swift it's weird but it works – Fattie Aug 20 '19 at 13:47
  • It looks like this ARTICLE https://www.natashatherobot.com/swift-enum-no-cases/ is largely the origin of that idiom – Fattie Aug 20 '19 at 13:48

9 Answers9

159

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.

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 do conflict, 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.MyClass doesn't work (the compiler knows what you mean, but it says it can't find such a class in the framework).

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.

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!

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 8
    Thanks for this answer. It works not only with Frameworks, but also with the Standard Library. You can "overwrite" Array, for example. Then "Array" refers to your own custom Array class, and Standard Library's Array is available as "Swift.Array". – George Aug 10 '14 at 18:47
  • 3
    @George And similarly for NSArray; if you overshadow it, you can still refer to it as `Foundation.NSArray`. – matt Aug 10 '14 at 19:41
  • 1
    So without having to sort through the history of thought on namespaces in the betas: where does this answer stand now? – Dan Rosenstark Jan 26 '15 at 03:01
  • 1
    @Yar as stated in the edits. The module name is an optional namespace if there is ambiguity, and there is now privacy so module names are hidden unless exposed and a name can be confined to a file. – matt Jan 26 '15 at 03:08
  • 2
    This has been bothering me for a long time now, it would appear that any Swift projects should not be using a prefix because of what Apple is claiming, however at this time a prefix is still required, even with the access modifiers. While you won't conflict with package or private classes in Apple's framework, anything declared public, for instance String, if you declare that again, or any new class, it will end up using yours, unless of course you are in the habit of referring to all classes with its namespace.... not good imo. – Oscar Gomez Mar 16 '16 at 19:36
  • That's awful Oscar, I'm going to continue prefixing every file with a namespace. Namespaces are such a core feature of a language i just can't understand why they were neglected. When done properly you can have very minimal naming without any rubbish prefixing. – LegendLength Apr 07 '17 at 16:51
126

Answered by SevenTenEleven in the Apple dev forum:

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".

Also Chris Lattner tweeted 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

Seems to be very different what I have been thinking.

eonil
  • 83,476
  • 81
  • 317
  • 516
  • 10
    Apple Dev forums... I've seen so much tumbleweed there you wouldn't believe! – Nicolas Miari Apr 06 '16 at 04:25
  • 1
    The link to the Apple dev forums is now broken, and Apple has not imported that thread into the new `forums.developer.apple.com` forums site, unfortunately. – Dai Feb 15 '17 at 02:07
  • 2
    @Dai It seems that's why we should avoid Apple forums for Q&A... But core dev team members don't seem to care much on SO. What a tragedy. – eonil Oct 08 '18 at 13:27
  • 1
    what you mean by tumbleweed? – Alexander Mills Nov 17 '18 at 02:58
  • 2
    @AlexanderMills I know this is over 4 years later, to answer your question: Imagine an old Western town like you see in the movies, it is empty, you see no people only tumbleweeds blowing across the streets. – John Apr 05 '23 at 18:30
  • finally now i understand the tunbleweed thing. – eonil Apr 09 '23 at 04:42
22

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

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
        }
    }
}

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

import Foundation

extension PackageOne {
    struct SubPackage {
    }
}

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'

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

Edit 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:

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

bWlrYWphdWhvbmVu
  • 1,764
  • 1
  • 11
  • 9
  • interesting, how was your testing? – user2727195 Jun 18 '14 at 19:35
  • 2
    Not sure what you mean by "testing" but I went ahead and started to build my app using above technique and it seems to work well so far with the caveat I added to my entry above. Im doing it mostly because Im used to organizing my code this way in other languages and would be grateful if any one with more knowledge could tell me its a bad idea until I go too far! :) – bWlrYWphdWhvbmVu Jun 19 '14 at 19:05
  • 1
    keep going... this is what we want... to be able to have a same name class in two different packages to be able to exist and referenced accordingly (more importantly different files) and if it doesn't work, the whole idea of namespace is a flop idea... – user2727195 Jun 23 '14 at 16:55
  • 1
    Any side effects using "struct" as a way to hack namespaces? – Alex Nolasco Sep 26 '14 at 15:55
  • Not that I have encountered in regards to performance an such. Xcode (6.1 GM) is in some rare cases complaining of types not existing but I believe this might be the case when not structuring code like this also. I recently solved one issue by adding all files to my Test-target which don't make any sense but it solved the problem. :) – bWlrYWphdWhvbmVu Oct 01 '14 at 21:31
  • @bWlrYWphdWhvbmVu, how do you deal with storyboards? The struct/extension approach works perfectly, however I cannot point to any namespaced class within my storyboard because it does not recognize such. – Stanislav Pankevich Jun 05 '15 at 16:41
  • see https://stackoverflow.com/questions/35673290/extension-of-a-nested-type-in-swift – Kirow Aug 30 '17 at 12:03
13

I believe this is achieved using:

struct Foo
{
    class Bar
    {
    }
}

Then it can be accessed using:

var dds = Foo.Bar();
Kevin Sylvestre
  • 37,288
  • 33
  • 152
  • 232
  • 1
    I'm still not that happy with the way namespaces are done... what if I've ten different classes in a namespace, and on top of that I prefer to keep classes in their individual files, don't want to bloat one file/struct with all classes, any suggestions Kevin. – user2727195 Jun 03 '14 at 20:10
  • @user2727195 Given the language just came out yesterday not yet :). I'm still looking through some of the documentation and this answer could turn out to be crazy. – Kevin Sylvestre Jun 03 '14 at 20:30
  • 2
    I wonder why they didn't think to include packages, that's what we need, not namespaces, I mean look at other high level languages like Java, C#, ActionScript, they all have packages, namespaces in this context is nothing different from using NS or other prefixes for your project classes – user2727195 Jun 04 '14 at 16:08
  • @JeanLeMoignan I'm getting a hold of this now... but seems bWlrYWphdWhvbmVu is having an issue there – user2727195 Jun 23 '14 at 16:50
  • I'm happy there's no package structure in Swift. They introduce a fine granularity where it's actually not that useful at all. They come with the kilometer long package import statements which is a noise in every single class. Module is a good enough compromise I think. – Janos Jul 15 '14 at 10:25
  • 1
    Cant help wondering if using structs as a way to hack namespaces can cause unknown issues. – Alex Nolasco Sep 26 '14 at 15:56
  • It's been a year since you guys talked about this. Are you still using this approach? Any advises against? Coming from ruby this is very tempting. Somebody refered to a problem with storyboards not recognizing the "namespaced" classes, but I'm gonna start using it for business classes like Users.Login Users.Signup Users.Login and so on... – Nuno Gonçalves Dec 30 '15 at 11:39
  • 1
    This is nice workaround for it. I tried using this approach but had to immediately stop. When I tried to namespace my view related classes (lets say a CustomTableViewCell), the autocomplete in interface builder didn't suggest it. I would have to manually copy and paste the class name for the view if I had used this approach. – ArG Jan 19 '17 at 06:51
  • 1
    Usually you'd use an `enum`, not a `struct`, so you can't instantiate a `Foo`. – Kevin Aug 20 '17 at 20:22
  • Exactly, this answer is more or less "wrong" - you use enum. https://www.natashatherobot.com/swift-enum-no-cases/ – Fattie Aug 20 '19 at 13:48
8
  • Namespaces are useful when you need to define class with the same name as class in existing framework.

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

You don't need to 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 UICollectionViewController from UIKit is declared in UIKit module.

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
Community
  • 1
  • 1
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
7

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

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

Also here is explained:

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

Ivan Genchev
  • 2,746
  • 14
  • 25
  • 2
    I'm looking for packages like construct as mentioned on your second link 6.4 Packages (Python), namespaces as nested types can't take very far, what if I've 10 different classes and in different files in a namespace or let's say a package??? – user2727195 Jun 03 '14 at 20:16
3

You can use extension to 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 Controllers and Views namespaces like in the example below, but it does illustrate how far it can go:

Profiles.swift:

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

Profiles/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
  }
}

Profiles/Views/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.

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
  }
}
Sebastien Martin
  • 1,341
  • 11
  • 25
2

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

From SevenTenEleven

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

AJ Venturella
  • 4,742
  • 4
  • 33
  • 62
2

Even though it is possible to implement namespaces using Framework and Libraries but the best solution is to use local packages using Swift Package Manager. Besides having access modifiers, this approach has some other benefits. As in Swift Package Manager, the files are managed based on the directory system, not their target member ship, you won't have to struggle with merge conflicts that arise frequently in teamworks. Furthermore, there is no need to set file memberships.

To check how to use local Swift packages refer to the following link: Organizing Your Code with Local Packages

Justin
  • 1,786
  • 20
  • 21