我想创建一个简单的距离函数来排序对象,同时从Swift2中的SQLite数据库获取。我使用的是很棒的SQLite.swift框架。
使用下面的代码,我可以获取最近的对象:
db.createFunction("distance") { (args) -> Binding? in
assert(args.count == 4)
if let lat1 = args[0] as? Double, let lon1 = args[1] as? Double, let lat2 = args[2] as? Double, let lon2 = args[3] as? Double {
let deltaLat = lat1 - lat2
let deltaLon = lon1 - lon2
return deltaLat * deltaLat + deltaLon * deltaLon * 0.46512281898705
}
return nil
}
let queryString = "SELECT * FROM objects where lat != "" and lng != "" ORDER BY distance(lat, lng, (lat), (lng)) ASC LIMIT (fetchLimit)"
let stmt = db.prepare(queryString)
for row in stmt {
print(row)
}
但是我想使用类型安全的SQL表达式而不使用查询字符串。我怎么能添加一个函数,能够使它像这样工作(这里的lat和lon值是表达式值,表示表中行和centerLat的位置,centerLon值表示从我计算对象的距离的中心点):
for row in db.order(distance(lat, lon, centerLat, centerLon).limit(fetchLimit) {
print(row)
}
目前还没有很好的方法来做到这一点(目前许多表达式构建助手都在SQLite.swift内部)。我鼓励你打开一个问题作为一个功能请求。
同时,由于这些值不需要加引号,因此可以执行以下操作:
func distance(
lat1: Expression<Double>, lng1: Expression<Double>,
lat2: Double, lng2: Double
) -> Expression<Double> {
return Expression(
literal: "distance((lat1.asSQL()), (lng1.asSQL()), ?, ?)",
lat2, lng2
)
}
当前的文档为这个问题带来了希望。然而,我不能得到示例代码编译与多个参数(上下文闭包类型'([Binding?]) -> Binding?'期望有1个参数,但在闭包体中使用了2个参数),应该可以:
import MobileCoreServices
let typeConformsTo: (Expression<String>, String) -> Expression<Bool> = (
try db.createFunction("typeConformsTo", deterministic: true) { UTI, conformsToUTI in
return UTTypeConformsTo(UTI, conformsToUTI)
}
)
https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md custom-sql-functions