Чтобы проверить, что ваш Singleton является защищенным потоком, я сделал небольшой образец. Вы можете найти код в этом Github repo в основном:
- создающего пучок нитей, просящих синглтон
- хранения каждый возвращенный объекта внутри массива
- проверки всех объектов, содержащихся в этом массиве являются одинаковыми
Я нашел несколько проблем (используя Xcode 6.2 ergo Swift 1.1), даже сбой компилятора. Итак, следуя this accepted SO answer Я изменил вашу реализацию Singleton, избегая классического использования GCD. Эти указатели и небезопасные изменяемые указатели вам нужно управлять, и я получаю аварии из-за этого
Так ваш класс Singleton теперь:
import Foundation
public class LocationManager: NSObject {
public class var sharedInstance: LocationManager {
struct Static {
static let instance: LocationManager = LocationManager()
}
return Static.instance
}
}
И проверить это, нужно подождать, пока все темы нет законченный. Как тест бегун работает на MainThread вам нужно использовать ожидание
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)
}
}
}
Важной частью это одна:
expect(self.allSingletonsEqual(inArray: allSingletons, singleton: LocationManager.sharedInstance)).toEventually(beTrue(), timeout: 10)
Здесь я просто вызов функции, чтобы убедиться, если каждый объект сохраняется такая же, как пройденный Singleton, и давая 10 секунд тайм-аут
весь класс Test:
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)
}
}
}
}
}