我正在使用 GRDB 库将 SQLite 与我的 iOS 应用程序项目集成。我在 AppDelegate.swift 中声明了一个 DatabaseQueue 对象,如下所示:
var DB : DatabaseQueue!
在同一个文件中,我提供了一个用于将上述对象连接到 SQLite 数据库的函数,该函数在应用程序开始运行时调用。我能够在我的一个 Controller 中使用它而不会出现任何问题(例如,该应用程序使用我连接到它的数据库运行时没有问题),如下所示:
var building : Building?
do {
try DB.write { db in
let building = Building.fetchOne(db, "SELECT * FROM Building WHERE number = ?", arguments: [bldgNumber])
}
} catch {
print(error)
}
但是,在另一个 Controller 中,相同的构造会遇到错误,
Value of optional type 'DatabaseQueue?' must be unwrapped to refer to member 'write' of wrapped base type 'DatabaseQueue'
唯一的区别(当然,除了代码之外)是 do-catch block 内有 return 语句,因为后者位于应该返回整数的函数(tableView for numberOfRowsInSection)内。错误的代码部分如下所示。
var locsCountInFloor : Int
do {
try DB.write { db in
if currentBuilding!.hasLGF == true {
locsCountInFloor = IndoorLocation.filter(bldg == currentBuilding! && level == floor).fetchCount(db)
} else {
locsCountInFloor = IndoorLocation.filter(bldg == currentBuilding! && level == floor + 1).fetchCount(db)
}
return locsCountInFloor
}
} catch {
return 0
}
任何帮助将不胜感激!
最佳答案
当您在 Swift 中遇到泛型类型问题时,通常会遇到这种情况,错误消息没有任何帮助。
真正的问题是:
DB.write
的参数和返回类型是通用的。它有一个类型参数T
。闭包参数的返回类型是T
,而write
方法本身返回T
。您传递的闭包不仅仅是一个表达式。这是一个多语句闭包。 Swift 不会从闭包中的语句推断出多语句闭包的类型。出于实际原因,这只是编译器的限制。
您的程序没有显式指定类型
T
或以其他方式提供让 Swift 推导出具体类型的约束。
程序的这些特征意味着 Swift 不知道用于 T
的具体类型。所以编译器的类型检查器/推导器失败了。您可能会收到有关此问题的错误消息。 (可能是一条难以理解的消息,但大概至少是相关的)。
但这不是您得到的,因为您将 DB
声明为 DatabaseQueue!
。
由于DB
是一个隐式解包的 optional ,类型检查器会通过(正如您可能猜到的那样)自动解包它来特殊处理它如果这样做会使语句类型 -检查语句何时不进行类型检查。在所有其他方面,DB
的类型只是普通的DatabaseQueue?
,一个常规的Optional
。
在这种情况下,即使自动展开,该语句也不会进行类型检查,因为我上面描述的错误:Swift 无法推导出具体类型来替代 T
。由于该语句不会以任何方式进行类型检查,因此 Swift 不会为您插入解包。然后它继续执行,就好像 DB
被声明为 DatabaseQueue?
。
由于 DatabaseQueue?
没有 write
方法(因为 Optional
没有 write
方法),调用DB.write
是错误的。所以 Swift 想要打印一条错误消息。但它“有帮助地”看到包装类型 DatabaseQueue
确实有一个 write
方法。此时它已经完全忘记了 DB
被声明为隐式解包。因此,它告诉您解开 DB
以获取 write
方法,即使如果没有遇到另一个,它会自动完成此操作此语句有错误。
所以无论如何,您需要告诉 Swift T
使用什么类型。我怀疑你想说的是:
var locsCountInFloor: Int
do {
locsCountInFloor = try DB.write { db in
...
将 DB.write
调用的结果分配给外部 locsCountInFloor
足以修复错误,因为您已经显式定义了 locsCountInFloor< 的类型
。由此,Swift 可以推断出对 DB.write
的调用的返回类型,并从中推断出闭包的类型。
关于ios - 使用 Xcode、Swift 和 GRDB,为什么我必须解开 DatabaseQueue?在我可以使用它的方法之前?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54478293/