Why Can Singleton classes be used as regular classes - ios

I was under the impression that the main reason for using singletons was to make sure that only one instance could be created in a program. I thought that the compiler wouldn't let you create instances of a singleton as if it would be a regular class.
In the following code I have a singleton where I'm creating multiple instances of it and it behaves as a regular class, but for some reason I was expecting an error.
What makes a singleton different than a regular class if it lets you create multiple instances?
// singleton class
class Car {
static let sharedCar = Car()
func run(){
print("Running")
}
}
// use
Car.sharedCar.run()
// other instances- I was expecting an error here
var jetta = Car()
jetta.run()
var cobalt = Car()
cobalt.run()
What am I missing here, can someone explain singletons?

I thought that the compiler wouldn't let you create instances of a singleton as if it would be a regular class.
There is no language feature called "singleton", it is an idiomatic pattern. If you leave your implementation of singleton open for instantiations from outside, there is nothing the compiler can do about that.
In the following code I have a singleton where I'm creating multiple instances of it and it behaves as a regular class, but for some reason I was expecting an error.
You should add a private init to make sure there are no external instantiations:
class Car {
static let sharedCar = Car()
func run(){
print("Running")
}
private init() {
}
}
Now you are the only one who can instantiate your class. Users of Car class outside of your code are forced to rely on sharedCar instance that you create for them.

Related

Mocking with Swift

Consider the following class named SomeClass written in Swift:
#objc class SomeClass: NSObject
{
var shouldCallBar = false
func foo()
{
if (shouldCallBar == true)
{
bar()
}
}
func bar()
{
}
}
For testing the above class foo() method (and similar scenarios mostly written in Objective-C) I was using OCMock like:
- (void) testFooBarShouldBeCalledWhenShouldCallBarIsTrue
{
SomeClass * someClass = [SomeClass new];
// Create mocks.
id mockSomeClass = OCMPartialMock(someClass);
// Expect.
[[mockSomeClass expect] bar];
// Stub.
someClass.shouldCallBar = YES;
// Run code under test.
[someClass foo];
// Verify.
[mockSomeClass verify];
// Stop mocking.
[mockSomeClass stopMocking];
}
But above test fails with Swift code as OCMock won't works well with Swift.
So I am considering something like entirely in Swift:
class SomeClassTests: XCTestCase
{
class MockSomeClass: SomeClass
{
var isBarCalled = false
override func bar()
{
isBarCalled = true
}
}
func testBarShouldBeCalledWhenTrue()
{
let someClass = MockSomeClass()
someClass.shouldCallBar = true
someClass.foo()
XCTAssertTrue(someClass.isBarCalled == true)
}
}
Note here I am subclassing the original class under test and overriding the bar(). I am not at all touching the foo() implementation.
But the downside is I am using MockSomeClass instance to test foo() of SomeClass. This is something I don't like and not recommended.
Is there any better solution to the problem above?
Notes:
I am not talking about Dependency Injection here. Dependency Injection is entirely different approach.
I face these kind of issues when testing UI code in UIViewController.
I have thought of Protocol based programming but was not able to come up with solution to problem above.
So, you want to test that one method (foo) does or does not call another method (bar). The foo method is the one under test, and the bar method is, in the wider sense, a dependent component.
If the invocation of bar has lasting side effects, you could get away with testing that the side effect is/isn't present, maybe by querying a property or similar. In that case you don't need mocks or similar.
If there are no side effects then you must substitute the dependency. To do so you need a seam at which you place code that can tell the test whether the method has been invoked or not. For that, I can only see the two options that Jon already discussed in the question you refer to.
You either put the two methods into separate classes, in which case the class boundary is the seam. Using a protocol, or just an informal convention, you can then completely replace the class that implements bar. Dependency injection comes in handy here.
If the two methods must stay in the same class then you have to use a subclass boundary as a seam, i.e. you use the fact that you can override methods and implement a test-specific sublass. It's easiest when you can use a mock framework. If that's not an option you have to write the code yourself, much like what you describe in your question.

iOS: Subclass singleton in swift

I have a framework where I have a singleton class, let's say Singleton. This class is used by other classes in the framework.
In the app project I want to subclass this singleton class, e.g. AppSingleton: Singleton. Is it possible? What is the right solution?
I provide a solution but it may be a little hacky.
Class A {
open class var shared: A {
return A.privateShared
}
private static let privateShared = A()
}
Class B {
open class var shared: B {
return A.privateShared
}
private static let privateShared = B()
}
I must clarify, this ways isn't perfect since it actually create 2 instance! So, it will technically not a singleton any more.
However, you can override the class B's property or method to call A.shared method or property instead. You must know what you are doing and consider use the other way to fix the problem you want to solve.

How to create Singleton in swift with arguments

I learn the Swift Language and i need to create a manager like a Parse sdk.
For exemple when you initialize your Parse in app you write
Parse.setApplication("...", applicationId:"...")
And later you can write code like this
Parse.doSomething()
The method doSomething() use initial context.
Can you show me in my class should look like? I try some singleton exemple, but a have MyClass.sharedAttribute.doSomething() in case
What you have shown is no indication of singletons whatsoever, it sounds and looks more like a static class with static members and properties:
class MyStatic {
static var appIdA : String?
class func setApplicationId(a : String) {
appIdA = a
}
class func doSomething() {
print(appIdA)
}
}
MyStatic.setApplicationId("blabla")
MyStatic.doSomething() // prints Optional("blabla")
Of course there is the possibility that internally the class is a singleton, but Parse does not seem to be one, just looking at the functions it exposes.
The code comments even state
/*!
The `Parse` class contains static functions that handle global configuration
for the Parse framework.
*/

Trouble mocking singleton for unit testing in Swift

Hello I am trying to mock one of the singletons I use to test that various view controllers actually call properly it's methods.
I have the singleton declared as such
public class ModelsManager {
static let sharedInstance = ModelsManager()
private init() {}
[...]
}
In the view controllers that use the singleton, it is set to a lazy computed property as such:
class MyViewController: UIViewController {
lazy var Models = {
return ModelsManager.sharedInstance
}()
[...]
}
I am trying to mock the ModelsManager singleton in my XCTestCase as such:
[...]
func testSomething() {
let vc = MyViewController(nibName: "MyView", bundle: nil)
var mockModelsManager = ModelsManagerMock.sharedInstance
vc.Models = mockModelsManager
[... do something that calls a function in ModelsManager...]
expect(mockModelsManager.flag) == true // Using Nimble here
}
class ModelsManagerMock: ModelsManager {
var flag = false
override func test() {
flag = true
}
}
In the expect() assertion I am getting Value of type 'ModelsManager' has no member 'flag'
What am I missing here?
EDIT
It appears that what I was missing was ModelsManagerMock.sharedInstance still returns IRModelsManager() from the superclass. Due to the fact that static can't be overwritten by subclasses, how do I get around this?
The correct solution must involve not subclassing your singleton. Creating a singleton with a private init method prohibits you from subclassing this method.
If the goal is to test the current functionality of the singleton, why do you want to add additional functionality to it? The key point of a singleton is that there should only ever be one. If you want to support more than one, you shouldn't make it a singleton, even if it's just for testing.

In swift, how to refer to topmost class when my class has subclass of same name

In Swift:
How can I assign a topmost myObject to the innerObj variable?
Does swift have some sort of namespace operator that lets me create an myObject from global namespace?
Consider the code below.
//my object that can init with a message=string
class MyObject {
init(message: String) {
println(message)
}
}
//here I define a global works fine
let global = myObject(message: "this works")
//other class
class ViewController: UIViewController {
//defines an inner class with same name
class MyObject {
func failsFunction(){
//cannot invoke initializer for type "ViewController.myObject" with an argument of type (String)
let innerObj = myObject("how can I refer to the topmost myObject here?")
}
}
}
My first answer would be "don't do that." It's technically legal because the two classes have unique scope, but it's confusing as all hell, and will come back to bite you 6 months from now when you are coming back to this code and don't remember that you have a global class and a child class of ViewController with the same name.
If you are going to ignore that advice, Lou provided your solution: Create a typeAlias at the top level and use that inside your ViewController class so that you can reference the global class inside ViewController.
Secondly, class names should start with an upper-case letter. So class myObject should be class MyObject. This is a documented convention of the language.
Thirdly, myObject is a dreadful name for a class. It doesn't give you any idea what the class is for. Even if this is a learning exercise, you should still follow good coding practices. It trains good habits, and test code has a way of finding itself in real projects, or posted as demo code somewhere, or whatever.
You need to alias it before you hide it with:
typealias GlobalMyObject = MyObject
One usual way is to bind your outer class into struct. This pattern is quite similar to creating a namespace. You could do it like this
struct MyNameSpace {
class myObject {
init(message: String) {
print(message)
}
}
}
//here I define a global works fine
let global = MyNameSpace.myObject(message: "this works")
//other class
class ViewController: UIViewController {
//defines a subclass with same name
class myObject {
func failsFunction(){
//cannot invoke initializer for type "ViewController.myObject" with an argument of type (String)
let innerObj = MyNameSpace.myObject(message: "how can I refer to the topmost myObject here?")
}
}
}
Then, you could use both the classes and the compiler determines the use cases differently for both.

Resources