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.
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 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.
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
I believe this is achieved using:
struct Foo
{
class Bar
{
}
}
Then it can be accessed using:
var dds = Foo.Bar();
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
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.
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
}
}
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
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."
Related
I have been asked to do testing in swift and I have no idea about swift
So, I was just reviewing the code and trying to make sense out of it.
I was in a file say xyzTests.swift where we wrote all the test case.
By going through the test cases written in the code, the first thing was something like this
func xyz() {
var failureMessage: String? = nil;
startSess(validity: 3)
}
In Javascript,one can only do something like this if
There is a function declared anywhere in the same file
if we are importing it from somewhere
So I searched in my file to find function declaration from startSess but wasn't able to find it. Then I clicked on jump to definition and found it some other file named utils.swift
internal func startSess(validity: Int = 1) {
}
I checked the file if there was at-least a reference of an import for at-least util but can't find any.
These are all the import statements in my code
import Foundation
#testable import session
Can someone explain me how we can use startSess?
I take it that the startSess is a function that is outside of any class then as it's being called in that way?
what #testable import session does is importing your entire workspace to be reachable from your test class. If you look in the right tab of the test file you can see that the target membership is only selected for tests (as it should be). And therefor it can't reach the rest of your code without the #testable import
See, There are various different methods to call a function from another file Some of them are as given below
(and Pardon me if I left any methods in this answer, I am open to edits :) )
As #Vollan said , importing the whole workspace , so you can access any function from any file anywhere in the project
Calling or Loading the file (in your case util.swift) and using the function in another file(xyz.swift)
ex: In xyz.swift,
func xyz() {
let a = util() //Loading the swiftfile
a.startSess(validity: 3) //using the function of swiftfile
}
making that function global which you want to use.
extension UIViewController { //In most cases UIViewController is used in all files so extending it helps
func startSess(validity: Int = 1) {
}
}
You can directly make that function global even if you are not using any extensions or any classes by using Foundation(As in any file Foundation is must imported in the Header of any SwiftFile)
Ex: - Make any SwiftFile say named abc.swift and in that file
import Foundation
func startSess(validity: Int = 1) {
//Your Code
}
Now, you can call this function by startSess(param) in any file in your whole project.
I want to write some unit testing code for a manager class, the function I would write for is using some small private functions. I will prepare a lot if I testing the public function, so I want to test those private functions. But in test target I can't call the private function directly.
So I wanna ask, is there's a way to test them without change them from private to internal or public?
So I wanna ask, is there's a way to test them without change them from private to internal or public?
Add an internal function that does nothing but call the private function. Probably it's best to do it in an extension:
class Foo
{
fileprivate func myPrivateFunction(p: Int) { ... }
}
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
You can probably find a way of using conditional compilation to omit the extension for release builds e.g.
#if DEBUG
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
#endif
Not tested the conditional thing to see if it works, it's borrowed from here https://ericasadun.com/2018/04/18/forcing-compiler-errors-in-swift/
Sadly no. There isn't a "VisibleForTesting" tag in Swift as there is in java.
However you can define a protocol which your manager class then implements including only the methods you want to test.
For example if your manager has a function called createViewModel that calls several private methods testing that the viewModel created matches that of what we expect we have implicitly tested the private methods work. You can set up your manager with different initial conditions to test all varieties and edge cases
I think you are looking for #testable imports. From Apple's documentation:
When you add the #testable attribute to an import statement for a
module compiled with testing enabled, you activate the elevated access
for that module in that scope. Classes and class members marked as
internal or public behave as if they were marked open. Other entities
marked as internal act as if they were declared public.
Interfaces are the solution.
This solution is a bit more complicated than the others, but can help you for multiple purposes, like uncoupling modules on your app.
Let's say you have a class Foo which has an object of type Bar, and you need to call doStuff().
Create a Protocol for Bar. So Foo is decoupled from Bar and becomes fully testable without exposing its content to Foo. Something like this:
protocol BarProtocol {
func doStuff()
}
class Bar:BarProtocol {
func doStuff() {
print("Hello world")
}
}
class Foo {
var bar:BarProtocol
init() {
self.bar = Bar()
self.bar.doStuff()
}
}
I know that
#testable import MyModule
gives ability to explore non-public members of MyModule from a "test" (built with "testTarget") module MyModuleTests.
I need the same functionality in my "non-test" module. Not in production, just in debug mode.
My question is: do you know how to do this?
And related (I think, harder question): what magic is actually happening behind #testable?
To answer your question, for debugging purposes, you can actually use this. Let's say you have a workspace MyAwesomeWkspace and a project inside MyAwesomeProject.
Now, create a new framework aka module called MyAwesomeModule. Inside that module create a non-public class called Person.
If you try to use the class Person inside MyAwesomeProject by doing import MyAwesomeModule and then something like let p = Person() you will have an error.
But if you do #testable import MyAwesomeModule, the magic happens and you can now use the class.
Basically #testable allows you to test things that you didn't declare public. The annotation only works with import as you can see it here.
So in order to work, the target is compiled with -enable-testing so that you can have access to non-public members. At least based on what's here
Because, by default, the debug build configuration is compiled with -enable-testing, the example I showed you will work. But if you change the build config to release, you'll see an error saying Module .. was not compiled for testing since the release config is not built with the flag.
The Swift access control model, as described in the Access Control
section of The Swift Programming Language (Swift 4), prevents an
external entity from accessing anything declared as internal in an app
or framework. By default, to be able to access these items from your
test code, you would need to elevate their access level to at least
public, reducing the benefits of Swift’s type safety.
Xcode provides a two-part solution to this problem:
When you set the Enable Testability build setting to Yes, which is
true by default for test builds in new projects, Xcode includes the
-enable-testing flag during compilation. This makes the Swift entities declared in the compiled module eligible for a higher level of access.
When you add the #testable attribute to an import statement for a
module compiled with testing enabled, you activate the elevated access
for that module in that scope. Classes and class members marked as
internal or public behave as if they were marked open. Other entities
marked as internal act as if they were declared public.
More here
Late edit: One of the cool parts of swift is that is open source. So if you want to dive deep into the "magic", check it out: https://github.com/apple/swift
#testable import <module_name> and -enable-testing
[Swift access modifiers]
[Swift module]
consumer side uses #testable import -> producer side should use `-enable-testing` flag
producer side: enable -enable-testing
Enable Testability(ENABLE_TESTABILITY) - YES
Other Swift Flags(OTHER_SWIFT_FLAGS) - -enable-testing
consumer side: #testable
internal(default) and public access level for class is visible for current module as open
internal(default) access level for others(struct, enum) is visible for current module as public
If you build test schema(consumer) with #testable but producer doesn't include -enable-testing you get
Module '<module_name>' was not compiled for testing
Some experiments:
SomeModule
internal class SomeInternalClass {
internal func foo() { }
}
public class SomePublicClass {
public func foo() { }
}
internal class SomeInternalStruct {
internal func foo() { }
}
internal enum SomeInternalEnum: String {
case foo = "hello world"
}
Tests: If you omit #testable next errors will occur
import XCTest
#testable import ExperimentsTests
class ExperimentsTestsTests: XCTestCase {
func testExample() throws {
let someInternalStruct = SomeInternalStruct() //Cannot find 'SomeInternalStruct' in scope
someInternalStruct.foo()
let someInternalEnum = SomeInternalEnum(rawValue: "") //Cannot find 'SomeInternalEnum' in scope
SomeInternalEnum.foo //Cannot find 'SomeInternalEnum' in scope
}
class SomePublicSubClass: SomePublicClass { //Cannot inherit from non-open class 'SomePublicClass' outside of its defining module
override func foo() { } //Overriding non-open instance method outside of its defining module
}
class SomeInternalSubClass: SomeInternalClass { //Cannot find type 'SomeInternalClass' in scope
override func foo() { } //Method does not override any method from its superclass
}
}
Does Swift support reflection? e.g. is there something like valueForKeyPath: and setValue:forKeyPath: for Swift objects?
Actually does it even have a dynamic type system, something like obj.class in Objective-C?
Looks like there's the start of some reflection support:
class Fruit {
var name="Apple"
}
reflect(Fruit()).count // 1
reflect(Fruit())[0].0 // "name"
reflect(Fruit())[0].1.summary // "Apple"
From mchambers gist, here:
https://gist.github.com/mchambers/fb9da554898dae3e54f2
If a class extends NSObject, then all of Objective-C's introspection and dynamism works. This includes:
The ability to ask a class about its methods and properties, and to invoke methods or set properties.
The ability to exchange method implementations. (add functionality to all instances).
The ability to generate and assign a new sub-class on the fly. (add functionality to a given instance)
One shortcoming of this functionality is support for Swift optional value types. For example Int properties can be enumerated and modified but Int? properties cannot. Optional types can be enumerated partially using reflect/MirrorType, but still not modified.
If a class does not extend NSObject, then only the new, very limited (and in progress?) reflection works (see reflect/MirrorType), which adds limited ability to ask a instance about its class and properties, but none of the additional features above.
When not extending NSObject, or using the '#objc' directive, Swift defaults to static- and vtable-based dispatch. This is faster, however, in the absence of a virtual machine does not allow runtime method interception. This interception is a fundamental part of Cocoa and is required for the following types of features:
Cocoa's elegant property observers. (Property observers are baked right in to the Swift language).
Non-invasively applying cross-cutting concerns like logging, transaction management (i.e Aspect Oriented Programming).
Proxies, message forwarding, etc.
Therefore its recommended that clases in Cocoa/CocoaTouch applications implemented with Swift:
Extend from NSObject. The new class dialog in Xcode steers in this direction.
Where the overhead of of a dynamic dispatch leads to performance issues, then static dispatch can be used - in tight loops with calls to methods with very small bodies, for example.
Summary:
Swift can behave like C++, with fast static/vtable dispatch and limited reflection. This makes it suitable for lower level or performance intensive applications, but without the complexity, learning curve or risk of error associated with C++
While Swift is a compiled language, the messaging style of method invocation adds the introspection and dynamism found in modern languages like Ruby and Python, just like Objective-C, but without Objective-C's legacy syntax.
Reference data: Execution overhead for method invocations:
static : < 1.1ns
vtable : ~ 1.1ns
dynamic : ~4.9ns
(actual performance depends on hardware, but the ratios will remain similar).
Also, the dynamic attribute allows us to explicitly instruct Swift that a method should use dynamic dispatch, and will therefore support interception.
public dynamic func foobar() -> AnyObject {
}
The documentation speaks about a dynamic type system, mainly about
Type and dynamicType
See Metatype Type (in Language Reference)
Example:
var clazz = TestObject.self
var instance: TestObject = clazz()
var type = instance.dynamicType
println("Type: \(type)") //Unfortunately this prints only "Type: Metatype"
Now assuming TestObject extends NSObject
var clazz: NSObject.Type = TestObject.self
var instance : NSObject = clazz()
if let testObject = instance as? TestObject {
println("yes!") //prints "yes!"
}
Currently, there is no reflection implemented.
EDIT: I was apparently wrong, see stevex's answer. There is some simple readonly reflection for properties build in, probably to allow IDEs to inspect object contents.
No reflect keyword in Swift 5, now you can use
struct Person {
var name="name"
var age = 15
}
var me = Person()
var mirror = Mirror(reflecting: me)
for case let (label?, value) in mirror.children {
print (label, value)
}
It seems that a Swift reflection API is not a high priority for Apple at the moment. But besides #stevex answer there is another function in the standard library that helps.
As of beta 6 _stdlib_getTypeName gets the mangled type name of a variable. Paste this into an empty playground:
import Foundation
class PureSwiftClass {
}
var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"
println( "TypeName0 = \(_stdlib_getTypeName(myvar0))")
println( "TypeName1 = \(_stdlib_getTypeName(myvar1))")
println( "TypeName2 = \(_stdlib_getTypeName(myvar2))")
println( "TypeName3 = \(_stdlib_getTypeName(myvar3))")
The output is:
TypeName0 = NSString
TypeName1 = _TtC13__lldb_expr_014PureSwiftClass
TypeName2 = _TtSi
TypeName3 = _TtSS
Ewan Swick's blog entry helps to decipher these strings:
e.g. _TtSi stands for Swift's internal Int type.
Mike Ash has a great blog entry covering the same topic.
You might want to consider using toString() instead. It is public and works just the same as _stdlib_getTypeName() with the difference that it also works on AnyClass, e.g. in a Playground enter
class MyClass {}
toString(MyClass.self) // evaluates to "__lldb_expr_49.MyClass"
Is there a way to do something akin to import <BLAH> as in actionscript? I've got some classes that I don't want to type the full class name out for every time I use them. That's why I'm trying to find an import as, or var C = ImportedClassThatIDontWantToTypeEveryTime. I've tried a few different ways, such as:
package com.mysite.blah {
// doesn't work
import com.mysite.ImportedClassThatIDontWantToTypeEveryTime as C;
// also doesn't work
import com.mysite.ImportedClassThatIDontWantToTypeEveryTime;
var C:Class = ImportedClassThatIDontWantToTypeEveryTime;
// ????
public class SomeOtherClass {
public function blah():void {
C.doSomething();
}
}
}
I know there is a way to do this - I've done it before years ago. However, I can't remember how to do it. Help?
What IDE are you using? I ask this because I haven't had to type out a class-path in full in years. The auto-complete features of both FlashDevelop and FlashBuilder will allow you to type the first couple of letters of the class you want in place, select it from a list, and it will automatically add the appropriate import statement to the top of your class.