我有一个单身类:
class Database {
static let instance:Database = Database()
private var db: Connection?
private init(){
do {
db = try Connection("\(path)/SalesPresenterDatabase.sqlite3")
}catch{print(error)}
}
}
现在我使用Database.instance.xxxxxx访问此类以在类中执行函数。但是,当我从另一个线程访问该实例时,它会抛出奇怪的结果,就像它试图创建另一个实例一样。我应该在同一个线程中引用该实例吗?
澄清奇怪的结果显示数据库I / O错误,因为两个实例一次尝试访问数据库
更新
有关数据库代码的更多信息,请参阅此问题:Using transactions to insert is throwing errors Sqlite.swift
答案 0 :(得分:5)
class var shareInstance: ClassName {
get {
struct Static {
static var instance: ClassName? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token, {
Static.instance = ClassName()
})
return Static.instance!
}
}
USE:let object:ClassName = ClassName.shareInstance
Swift 3.0
class ClassName {
static let sharedInstance: ClassName = { ClassName()} ()
}
USE:let object:ClassName = ClassName.shareInstance
答案 1 :(得分:3)
在Swift 3.0中添加一个私有init以防止其他人使用default()初始化程序。
class ClassName {
static let sharedInstance = ClassName()
private init() {} //This prevents others from using the default '()' initializer for this class.
}
答案 2 :(得分:0)
单线程类。
final public class SettingsThreadSafe {
public static let shared = SettingsThreadSafe()
private let concurrentQueue = DispatchQueue(label: "com.appname.typeOfQueueAndUse", attributes: .concurrent)
private var settings: [String: Any] = ["Theme": "Dark",
"MaxConsurrentDownloads": 4]
private init() {}
public func string(forKey key: String) -> String? {
var result: String?
concurrentQueue.sync {
result = self.settings[key] as? String
}
return result
}
public func int(forKey key: String) -> Int? {
var result: Int?
concurrentQueue.sync {
result = self.settings[key] as? Int
}
return result
}
public func set(value: Any, forKey key: String) {
concurrentQueue.async( flags: .barrier ) {
self.settings[key] = value
}
}
}
用于测试单例类的单元。
func testConcurrentUsage() {
let concurrentQueue = DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
let expect = expectation(description: "Using SettingsThreadSafe.shared from multiple threads shall succeed")
let callCount = 300
for callIndex in 1...callCount {
concurrentQueue.async {
SettingsThreadSafe.shared.set(value: callIndex, forKey: String(callIndex))
}
}
while SettingsThreadSafe.shared.int(forKey: String(callCount)) != callCount {
// nop
}
expect.fulfill()
waitForExpectations(timeout: 5) { (error) in
XCTAssertNil(error, "Test expectation failed")
}
}