I am trying to learn testing with Quick and Nimble and I wrote simple singleton and some tests
Singleton:
public class LocationManager : NSObject {
// Singleton
public class var sharedInstance : LocationManager {
struct Static {
static var instance : LocationManager?
static var token : dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = LocationManager()
}
return Static.instance!
}
}
My tests:
class LocationManagerSpec: QuickSpec {
override func spec() {
describe("Location manager") {
let locationManager = LocationManager.sharedInstance
context("initialized") {
it("is not nil") {
expect(locationManager).notTo(beNil())
}
it("is unique") {
let tempLocationManager = LocationManager()
expect(locationManager).notTo(equal(tempLocationManager))
}
it("and shared instances are same") {
let tempLocationManager = LocationManager.sharedInstance
expect(locationManager).to(equal(tempLocationManager))
}
}
}
}
}
How can I test my singleton is thread safe?
To test that your Singleton is Thread safe I've made a little sample. You can find all code in this Github repo basically:
creating a bunch of threads asking for the singleton
storing every returned object inside an Array
checking all objects contained in that array are the same
I've found several problems (using Xcode 6.2 ergo Swift 1.1), even compiler crashes. So following this accepted SO answer I've changed your Singleton implementation avoiding the classic use of GCD. These pointers and unsafe mutable pointers you need to manage, and I was getting crashes because of that
So your Singleton class is now:
import Foundation
public class LocationManager: NSObject {
public class var sharedInstance: LocationManager {
struct Static {
static let instance: LocationManager = LocationManager()
}
return Static.instance
}
}
And to test it, you need to wait until all Threads have finished. As the test runner runs on the MainThread you need to use a expectation
describe("Accesing Location manager from multiple concurrent threads") {
context("When created") {
it("should return always the same object for every of these 500 threads") {
var allSingletons = Array<LocationManager>()
for i in 1...10 {
println("Launching thread \(i)")
dispatch_async(self.globalBackgroundQueue) {
allSingletons.append(LocationManager.sharedInstance)
}
}
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
}
}
}
The important part is this one:
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
Here I'm just calling a function to be sure if every stored object is the same as the passed Singleton, and giving a 10 seconds timeout
The whole Test class:
import Quick
import Nimble
import QuickNimbleExample
class LocationManagerSpec: QuickSpec {
var globalBackgroundQueue: dispatch_queue_t {
return dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0)
}
func allSingletonsEqual(#inArray: Array<LocationManager>, singleton: LocationManager) -> Bool {
for loc in inArray {
if loc != singleton {
return false
}
}
return true
}
override func spec() {
describe("Accesing Location manager from multiple concurrent threads") {
context("When created") {
it("should return always the same object for every of these 500 threads") {
var allSingletons = Array<LocationManager>()
for i in 1...10 {
println("Launching thread \(i)")
dispatch_async(self.globalBackgroundQueue) {
allSingletons.append(LocationManager.sharedInstance)
}
}
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
}
}
}
}
}
Related
What is the best way to detect in runtime if the code is running a test or the production app.
Basically I want to allow a setter just for testing purposes. Something like:
class LoginService {
private static var LoginService instance = LoginService();
public var sharedInstance: LoginService {
get{
return instance;
}
set{
if(inRunningTests()){
instance = newValue;
} else {
fatalError("This setter is just for testing")
}
}
}
static func isRunningTests() -> Bool {
// ????
}
}
My working solution
static var isRunningTests : Bool {
get {
return NSClassFromString("XCTest") != nil;
}
}
For unit tests you can use;
func isTesting() -> Bool {
if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] == nil {
return false
}
return true
}
So, i am creating a Singleton class as below, and i need few instance variables in this class, such that any team member can access the instance variable and get the values. To do that, i will need to initialize these instance variables to a certain value at the beginning itself.
But i get a compilation error, saying "missing argument for parameter 'doesValueExists' in call".
What exactly i m doing wrong here ?
class ABC_Util {
private var doesValueExists: Bool
private var arrValues: NSMutableArray?
class var sharedInstance: ABC_Util {
struct ABC_UtilSingleton {
static let instance = ABC_Util()
}
return ABC_UtilSingleton.instance
}
init(doesValueExists: Bool, arrValues: NSMutableArray?) {
self.doesValueExists = self.checkValueExists()
self.arrValues = self.getArrayOfValues()
}
//method
internal func checkValueExists() -> Bool {
}
//method
internal func getArrayOfValues() -> NSMutableArray? {
}
}
Your initializer for ABC_Util is declared as:
init(doesValueExists:Bool, arrValues:NSMutableArray?) {
Therefore you cannot say
static let instance = ABC_Util()
The expression ABC_Util() would correspond to an initializer with no parameters, and you do not have such an initializer. You must say:
static let instance = ABC_Util(doesValueExists:someBool, arrValues:someArray)
(with appropriate values, of course).
You have to use your initializer in order to initialize your variables.
class ABC_Util {
private var doesValueExists:Bool
private var arrValues:NSMutableArray?
class var sharedInstance: ABC_Util
{
struct ABC_UtilSingleton
{
static let instance = ABC_Util(doesValueExists: true, arrValues: nil)
}
return ABC_UtilSingleton.instance
}
init(doesValueExists:Bool, arrValues:NSMutableArray?) {
self.doesValueExists = doesValueExists
self.arrValues = arrValues
}
//method
internal func checkValueExists()-> Bool
{
return true
}
//method
internal func getArrayOfValues()-> NSMutableArray?
{
return nil
}
}
And I recommend you to change your singleton declaration to the suggested syntax
static let sharedInstance: ABC_Util = ABC_Util(doesValueExists: true, arrValues: nil)
You could use as below.
class ABC_Util {
private var doesValueExists:Bool = false
private var arrValues:NSMutableArray?
class var sharedInstance: ABC_Util {
struct ABC_UtilSingleton {
static let instance = ABC_Util(doesValueExists: false, arrValues: ["a", "b", "c"])
}
return ABC_UtilSingleton.instance
}
init(doesValueExists:Bool, arrValues:NSMutableArray?) {
self.doesValueExists = self.checkValueExists()
self.arrValues = self.getArrayOfValues()
}
//method
internal func checkValueExists()-> Bool{
return self.doesValueExists
}
//method
internal func getArrayOfValues()-> NSMutableArray?{
return arrValues
}
}
i got the solution, when i tried this, worked fine!
class ABC_Util {
var doesValueExists:Bool = false
var arrValues:NSMutableArray? = nil
class var sharedInstance: ABC_Util
{
struct ABC_UtilSingleton
{
static let instance = ABC_Util()
}
return ABC_UtilSingleton.instance
}
init() {
self.doesValueExists = self.checkValueExists()
self.arrValues = self.getArrayOfValues()
}
//method
internal func checkValueExists()-> Bool
{
//return true/false
}
//method
internal func getArrayOfValues()-> NSMutableArray?
{
//return array/nil
}
}
I'm an android app developer and a beginner in swift. I'm trying to implement a singleton class whose data members are shared throughout the app (like Settings).
Getting this done in android is pretty simple but I'm breaking my head to do it in swift.
Below is the code I've tried ..
public class DataSet
{
public var notificationOnOff: Bool!
public var interval: Int!
public var alert: String!
init()
{
self.notificationOnOff = true
self.interval = 1;
self.alert = nil;
}
init (onOff: Bool) {
self.notificationOnOff = onOff
}
init (time: Int) {
self.interval = time
}
init (stop: String) {
self.alert = stop
}
}
This class implementation couldn't persist the data.
Is this the right way of doing it?
EDIT
For example, when I click switch in Settings view controller, I'm setting notificationOnOff like ..
dataset.notificationOnOff = DataSet(onOff: true) // value is set and able to print it
and using this value in another class like...
if dataset.notificationOnOff
{
// do some stuff
}
So basically, the value is persisting only within the Setting class but not when I switch to other class.
Solved!
I have used the below code to successfully implement this..
var instance: DataSet?
class Dataset {
...
class var sharedInstance: DataSet {
struct Static {
static var instance: DataSet?
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token) {
Static.instance = DataSet()
}
return Static.instance!
}
}
and in the other classes ..
dataset = Dataset.sharedInstance;
I'm trying to implement an image downloader class. It's a singleton implementation. The idea is to ask the instance to download an image and register as an observer for that image download. This is what I came up with so far:
public protocol ImageDownloaderDelegate {
func imageDownloadFinished(success: Bool)
}
public class ImageDownloader {
var list: [Int64] = []
var observer: [Int64:[ImageDownloaderDelegate]] = [:]
var downloading: Bool = false
public func downloadImageWithId(immutableId: Int64, delegate: ImageDownloaderDelegate) {
// Add Id to download list
if (!contains(list, immutableId)) {
list.append(immutableId)
}
// Add Observer
var observerList = observer[immutableId]
if (observerList == nil) {
observerList = [delegate]
} else if (!contains(observerList, delegate)) {
observerList!.append(delegate)
}
observer[immutableId] = observerList
// Start to download
if (!downloading) {
self.downloadNextImage()
}
}
private func downloadNextImage() {
...
}
/// A shared instance of the class
public class var defaultImageDownloader: ImageDownloader {
struct Singleton {
static let instance = ImageDownloader()
}
return Singleton.instance
}
}
I get the following error:
'ImageDownloaderDelegate' is not convertible to 'S.Generator.Element -> L'
Any help is much appreciated
You're not passing the correct arguments to the contains function, which expects a collection and a predicate (closure).
You need to do
public protocol ImageDownloaderDelegate : class {
func imageDownloadFinished(success: Bool)
}
public class ImageDownloader {
var list: [Int64] = []
var observer: [Int64:[ImageDownloaderDelegate]] = [:]
var downloading: Bool = false
public func downloadImageWithId(immutableId: Int64, delegate: ImageDownloaderDelegate) {
// Add Id to download list
if (!contains(list, immutableId)) {
list.append(immutableId)
}
// Add Observer
var observerList = observer[immutableId]
if (observerList == nil) {
observerList = [delegate]
} else if !contains(observerList!, { observer in observer === delegate }) {
observerList!.append(delegate)
}
observer[immutableId] = observerList
// Start to download
if (!downloading) {
self.downloadNextImage()
}
}
private func downloadNextImage() {
...
}
/// A shared instance of the class
public class var defaultImageDownloader: ImageDownloader {
struct Singleton {
static let instance = ImageDownloader()
}
return Singleton.instance
}
}
This is a relatively common design pattern:
https://stackoverflow.com/a/17015041/743957
It allows you to return a subclass from your init calls.
I'm trying to figure out the best method of achieving the same thing using Swift.
I do know that it is very likely that there is a better method of achieving the same thing with Swift. However, my class is going to be initialized by an existing Obj-C library which I don't have control over. So it does need to work this way and be callable from Obj-C.
Any pointers would be very much appreciated.
I don't believe that this pattern can be directly supported in Swift, because initialisers do not return a value as they do in Objective C - so you do not get an opportunity to return an alternate object instance.
You can use a type method as an object factory - a fairly contrived example is -
class Vehicle
{
var wheels: Int? {
get {
return nil
}
}
class func vehicleFactory(wheels:Int) -> Vehicle
{
var retVal:Vehicle
if (wheels == 4) {
retVal=Car()
}
else if (wheels == 18) {
retVal=Truck()
}
else {
retVal=Vehicle()
}
return retVal
}
}
class Car:Vehicle
{
override var wheels: Int {
get {
return 4
}
}
}
class Truck:Vehicle
{
override var wheels: Int {
get {
return 18
}
}
}
main.swift
let c=Vehicle.vehicleFactory(4) // c is a Car
println(c.wheels) // outputs 4
let t=Vehicle.vehicleFactory(18) // t is a truck
println(t.wheels) // outputs 18
The "swifty" way of creating class clusters would actually be to expose a protocol instead of a base class.
Apparently the compiler forbids static functions on protocols or protocol extensions.
Until e.g. https://github.com/apple/swift-evolution/pull/247 (factory initializers) is accepted and implemented, the only way I could find to do this is the following:
import Foundation
protocol Building {
func numberOfFloors() -> Int
}
func createBuilding(numberOfFloors numFloors: Int) -> Building? {
switch numFloors {
case 1...4:
return SmallBuilding(numberOfFloors: numFloors)
case 5...20:
return BigBuilding(numberOfFloors: numFloors)
case 21...200:
return SkyScraper(numberOfFloors: numFloors)
default:
return nil
}
}
private class BaseBuilding: Building {
let numFloors: Int
init(numberOfFloors:Int) {
self.numFloors = numberOfFloors
}
func numberOfFloors() -> Int {
return self.numFloors
}
}
private class SmallBuilding: BaseBuilding {
}
private class BigBuilding: BaseBuilding {
}
private class SkyScraper: BaseBuilding {
}
.
// this sadly does not work as static functions are not allowed on protocols.
//let skyscraper = Building.create(numberOfFloors: 200)
//let bigBuilding = Building.create(numberOfFloors: 15)
//let smallBuilding = Building.create(numberOfFloors: 2)
// Workaround:
let skyscraper = createBuilding(numberOfFloors: 200)
let bigBuilding = createBuilding(numberOfFloors: 15)
let smallBuilding = createBuilding(numberOfFloors: 2)
Since init() doesn't return values like -init does in Objective C, using a factory method seems like the easiest option.
One trick is to mark your initializers as private, like this:
class Person : CustomStringConvertible {
static func person(age: UInt) -> Person {
if age < 18 {
return ChildPerson(age)
}
else {
return AdultPerson(age)
}
}
let age: UInt
var description: String { return "" }
private init(_ age: UInt) {
self.age = age
}
}
extension Person {
class ChildPerson : Person {
let toyCount: UInt
private override init(_ age: UInt) {
self.toyCount = 5
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(toyCount) toys!"
}
}
class AdultPerson : Person {
let beerCount: UInt
private override init(_ age: UInt) {
self.beerCount = 99
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(beerCount) beers!"
}
}
}
This results in the following behavior:
Person.person(10) // "ChildPerson: I'm 10. I have 5 toys!"
Person.person(35) // "AdultPerson: I'm 35. I have 99 beers!"
Person(35) // 'Person' cannot be constructed because it has no accessible initializers
Person.ChildPerson(35) // 'Person.ChildPerson' cannot be constructed because it has no accessible initializers
It's not quite as nice as Objective C, since private means all the subclasses need to be implemented in the same source file, and there's that the minor syntax difference Person.person(x) (or Person.create(x) or whatever) instead of simply Person(x), but practically speaking, it works the same.
To be able to instantiate literally as Person(x), you could turn Person into a proxy class which contains a private instance of the actual base class and forwards everything to it. Without message forwarding, this works for simple interfaces with few properties/methods but it gets unwieldy for anything more complex :P
I think actually the Cluster pattern can be implemented in Swift using runtime functions. The main point is to replace the class of your new object with a subclass when initializing. The code below works fine though I think more attention should be paid to subclass' initialization.
class MyClass
{
var name: String?
convenience init(type: Int)
{
self.init()
var subclass: AnyClass?
if type == 1
{
subclass = MySubclass1.self
}
else if type == 2
{
subclass = MySubclass2.self
}
object_setClass(self, subclass)
self.customInit()
}
func customInit()
{
// to be overridden
}
}
class MySubclass1 : MyClass
{
override func customInit()
{
self.name = "instance of MySubclass1"
}
}
class MySubclass2 : MyClass
{
override func customInit()
{
self.name = "instance of MySubclass2"
}
}
let myObject1 = MyClass(type: 1)
let myObject2 = MyClass(type: 2)
println(myObject1.name)
println(myObject2.name)
protocol SomeProtocol {
init(someData: Int)
func doSomething()
}
class SomeClass: SomeProtocol {
var instance: SomeProtocol
init(someData: Int) {
if someData == 0 {
instance = SomeOtherClass()
} else {
instance = SomethingElseClass()
}
}
func doSomething() {
instance.doSomething()
}
}
class SomeOtherClass: SomeProtocol {
func doSomething() {
print("something")
}
}
class SomethingElseClass: SomeProtocol {
func doSomething() {
print("something else")
}
}
Basically you create a protocol that your class cluster inherits from. You then wrap around an instance variable of the same type and choose which implementation to use.
For example, if you were writing an array class that switched between a LinkedList or a raw array then SomeOtherClass and SomethingElseClass might be named LinkedListImplementation or PlainArrayImplementation and you could decide which one to instantiate or switch to based on whatever is more efficient.
There is a way to achieve this. Whether it is good or bad practice is for another discussion.
I have personally used it to allow for extension of a component in plugins without exposing the rest of the code to knowledge of the extensions. This follows the aims of the Factory and AbstractFactory patterns in decoupling code from the details of instantiation and concrete implementation classes.
In the example case the switching is done on a typed constant to which you would add in extensions. This kinda contradicts the above aims a little technically - although not in terms of foreknowledge. But in your case the switch might be anything - the number of wheels for example.
I don’t remember if this approach was available in 2014 - but it is now.
import Foundation
struct InterfaceType {
let impl: Interface.Type
}
class Interface {
let someAttribute: String
convenience init(_ attribute: String, type: InterfaceType = .concrete) {
self.init(impl: type.impl, attribute: attribute)
}
// need to disambiguate here so you aren't calling the above in a loop
init(attribute: String) {
someAttribute = attribute
}
func someMethod() {}
}
protocol _Factory {}
extension Interface: _Factory {}
fileprivate extension _Factory {
// Protocol extension initializer - has the ability to assign to self, unlike class initializers.
init(impl: Interface.Type, attribute: String) {
self = impl.init(attribute: attribute) as! Self;
}
}
Then in a concrete implementation file ...
import Foundation
class Concrete: Interface {
override func someMethod() {
// concrete version of some method
}
}
extension InterfaceType {
static let concrete = InterfaceType(impl: Concrete.self)
}
For this example Concrete is the "factory" supplied default implementation.
I have used this, for example, to abstract the details of how modal dialogs were presented in an app where initially UIAlertController was being used and migrated to a custom presentation. None of the call sites needed changing.
Here is a simplified version that does not determine the implementation class at runtime. You can paste the following into a Playground to verify its operation ...
import Foundation
class Interface {
required init() {}
convenience init(_ discriminator: Int) {
let impl: Interface.Type
switch discriminator {
case 3:
impl = Concrete3.self
case 2:
impl = Concrete2.self
default:
impl = Concrete1.self
}
self.init(impl: impl)
}
func someMethod() {
print(NSStringFromClass(Self.self))
}
}
protocol _Factory {}
extension Interface: _Factory {}
fileprivate extension _Factory {
// Protocol extension initializer - has the ability to assign to self, unlike class initializers.
init(impl: Interface.Type) {
self = impl.init() as! Self;
}
}
class Concrete1: Interface {}
class Concrete2: Interface {}
class Concrete3: Interface {
override func someMethod() {
print("I do what I want")
}
}
Interface(2).someMethod()
Interface(1).someMethod()
Interface(3).someMethod()
Interface(0).someMethod()
Note that Interface must actually be a class - you can't collapse this down to a protocol avoiding the abstract class even if it had no need for member storage. This is because you cant invoke init on a protocol metatype and static member functions cannot be invoked on protocol metatypes. This is too bad as that solution would look a lot cleaner.
We can take advantage of a compiler quirk - self is allowed to be assigned in protocol extensions - https://forums.swift.org/t/assigning-to-self-in-protocol-extensions/4942.
Thus, we can have in place something like this:
/// The sole purpose of this protocol is to allow reassigning `self`
fileprivate protocol ClusterClassProtocol { }
extension ClusterClassProtocol {
init(reassigningSelfTo other: Self) {
self = other
}
}
/// This is the base class, the one that gets circulated in the public space
class ClusterClass: ClusterClassProtocol {
convenience init(_ intVal: Int) {
self.init(reassigningSelfTo: IntChild(intVal))
}
convenience init(_ stringVal: String) {
self.init(reassigningSelfTo: StringChild(stringVal))
}
}
/// Some private subclass part of the same cluster
fileprivate class IntChild: ClusterClass {
init(_ intVal: Int) { }
}
/// Another private subclass, part of the same cluster
fileprivate class StringChild: ClusterClass {
init(_ stringVal: String) { }
}
Now, let's give this a try:
print(ClusterClass(10)) // IntChild
print(ClusterClass("abc")) // StringChild
This works the same as in Objective-C, where some classes (e.g. NSString, NSArray, NSDictionary) return different subclasses based on the values given at initialization time.