How to use Namespaces in Swift?

IosMacosSwift

Ios Problem Overview


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.

Ios Solutions


Solution 1 - Ios

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.

Solution 2 - Ios

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.

Solution 3 - Ios

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

Solution 4 - Ios

I believe this is achieved using:

struct Foo
{
    class Bar
    {
    }
}

Then it can be accessed using:

var dds = Foo.Bar();

Solution 5 - Ios

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

Solution 6 - Ios

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.

Solution 7 - Ios

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

Solution 8 - Ios

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

Solution 9 - Ios

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlassejView Question on Stackoverflow
Solution 1 - IosmattView Answer on Stackoverflow
Solution 2 - IoseonilView Answer on Stackoverflow
Solution 3 - IosbWlrYWphdWhvbmVuView Answer on Stackoverflow
Solution 4 - IosKevin SylvestreView Answer on Stackoverflow
Solution 5 - IosBartłomiej SemańczykView Answer on Stackoverflow
Solution 6 - IosIvan GenchevView Answer on Stackoverflow
Solution 7 - IosSebastien MartinView Answer on Stackoverflow
Solution 8 - IosAJ VenturellaView Answer on Stackoverflow
Solution 9 - IosJustinView Answer on Stackoverflow