Using Xcode 6.3, I created a very simple, contrived command line tool in Swift. It contains three modules.
The main module:
import Foundation
let displayer = ValueDisplayer()
displayer.displayValue()
A ValueDisplayer module:
import Foundation
class ValueDisplayer {
func displayValue() {
println("The value is \(ValueProvider.instance.value)")
}
}
and a ValueProvider module:
import Foundation
public class ValueProvider {
class var instance: ValueProvider {
struct Static {
static let instance = ValueProvider()
}
return Static.instance
}
var value: Int {
return Int(arc4random())
}
}
This all compiled and ran successfully. However, I then decided to convert the ValueProvider to a framework. I created a Cocoa Framework target, and moved the ValueProvider module into it instead of in the command line target. I modified the ValueDisplayer module to this:
import Foundation
import ValueProvider
class ValueDisplayer {
func displayValue() {
println("The value is \(ValueProvider.instance.value)")
}
}
and configured the command line tool to link against the framework. Now I get the following compilation error in the ValueDisplayer module related to the println statement:
Module 'ValueProvider' has no member named 'instance'
I'm confused as to why the code doesn't work anymore. I'm wondering if the ValueProvider class is not being qualified correctly anymore, only it is unclear how that should be done.
What is needed to allow the command line tool to compile by linking against the framework?
Pure-singleton classes must be marked as final to avoid inheritance confusion. In swift, you can use structure also to achieve the same concept. A programmer cannot inherit the pure-singleton class. When you try to inherit any class in swift, you must call the constructor of the superclass.
In Swift, Singleton is a design pattern that ensures a class can have only one object. Such a class is called singleton class. An initializer allows us to instantiate an object of a class. And, making the initializer of a class restricts the object creation of the class from outside of the class.
You don't destroy a singleton. A singleton is created the first time anyone needs it, and is never destroyed as long as the application lives.
If the Singleton is nil it creates a new instance. This is actually the only good way to set up a Singleton. If you have a regular object that you can't deinitialize it's a memory problem. Singletons are no different, except that you have to write a function to do it.
public
is "opt-in". It is not applied magically to members of a public entity; you must apply it explicitly to a member of a public entity if you want that member to be public as well. You made the class ValueProvider
public but you did not make its class var instance
public, so it is not visible from another module.
So, you would need to rewrite like this:
public class ValueProvider {
public class var instance: ValueProvider {
// ...
}
public var value: Int {
// ...
}
}
[And by the way, a file is not a module. A framework is a module. That is why you have to change your code when you move it from merely being in a separate file to being in a different framework.]
I got program to build and run. What I had to do was go to the Build Phases for the framework and remove the generated header file from the Headers section. I don’t know why this makes things work. My understanding is that header is needed to help with Objective-C interaction. If the program had needed to interact with Objective-C as well as Swift, I’m wondering how anyone could get things to work properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With