How to use Namespaces in Swift?

后端 未结 8 1926
Happy的楠姐
Happy的楠姐 2020-11-28 01:53

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.

相关标签:
8条回答
  • 2020-11-28 02:17

    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

    0 讨论(0)
  • 2020-11-28 02:17
    • 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
    
    0 讨论(0)
  • 2020-11-28 02:25

    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.

    0 讨论(0)
  • 2020-11-28 02:32

    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.

    0 讨论(0)
  • 2020-11-28 02:35

    I believe this is achieved using:

    struct Foo
    {
        class Bar
        {
        }
    }
    

    Then it can be accessed using:

    var dds = Foo.Bar();
    
    0 讨论(0)
  • 2020-11-28 02:36

    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
      }
    }
    
    0 讨论(0)
提交回复
热议问题