How to use Namespaces in Swift? How to use Namespaces in Swift? ios ios

How to use Namespaces in Swift?


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.


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 FrameworkAimport FrameworkBFrameworkA.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.


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 Foundationstruct PackageOne {}

PackageTwo.swift

import Foundationstruct 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 Foundationextension 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