在Swift中使用Singleton模式创建全局SQLite DB连接



我检测Singleton实例上是否存在连接,如果不存在,它将在应用程序启动时打开一个新连接。然而,理想情况下,我希望在首次创建Singleton时激发open函数,而不必显式调用它并将其分配给类中的某个变量。

我现在拥有代码的方式违背了共享Singleton的目的,因为我只访问静态连接对象。当我尝试将静态conn更改为实例变量时,我得到错误Instance member 'conn' cannot be used on type 'DBConnection'

非工作代码

class DBConnection {
static let shared = DBConnection()
var conn: Connection? = nil

private init() { }

static func open(dbPath: URL) throws {
var dbConnections: [Connection] = []

do {
let dbConnection = try Connection("(dbPath)/db.sqlite3")
dbConnections.append(dbConnection)
print("found connection, (dbConnections)")
} catch {
throw SQLiteDBError.couldNotOpenConnection
}

self.conn = dbConnections[0]
print("successfully opened connection")
}
}

如何在init上调用Singleton类中的私有函数并将其分配给某个变量?

当前工作代码

class DBConnection {
static let shared = DBConnection()
static var conn: Connection?

private init() { }

static func open(dbPath: URL) throws {
var dbConnections: [Connection] = []

do {
let dbConnection = try Connection("(dbPath)/db.sqlite3")
dbConnections.append(dbConnection)
print("found connection, (dbConnections)")
} catch {
throw SQLiteDBError.couldNotOpenConnection
}

self.conn = dbConnections[0]
print("successfully opened connection")
}
}

主应用程序初始化

@main
struct MyApp: App {

init() {
if DBConnection.conn != nil {
do {
try DBConnection.open(dbPath: FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask)[0])
} catch {
print("error")
}
} else {
print("Connection already existed")
}
}
....
}

当我试图将静态连接更改为实例变量时,我会得到错误Instance member 'conn' cannot be used on type 'DBConnection'

考虑到您如何使用open:,这是有意义的

try DBConnection.open(dbPath: FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask)[0])

现在,openDBConnection的一个静态方法,这意味着您可以在不需要类实例的情况下调用它。它类似于";类方法";在Objective-C中。但在你破碎的代码中,你有:

var conn:连接?=无

因此conn是一个实例变量,即一个仅存在于类实例上下文中的变量。一个快速的解决方案是使open非静态:

func open(dbPath: URL) throws {

然后使用共享实例调用它:

try DBConnection.shared.open(dbPath: FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask)[0])

(注意添加了shared。(

然而,理想情况下,我希望在首次创建Singleton时激发open函数,而不必显式调用它并将其分配给类中的某个变量。

如果希望在创建单例时打开连接,可以从初始化器内部调用open

另一个方向是让connopen都保持静态,这样open就可以访问conn,并让类本身成为singleton。然后可以消除shared变量。

然而,我认为最好的选择是如上所述,使connopen非静态,去掉shared实例,而只跟踪您创建的DBConnection对象。

最新更新