问题描述
我使用 Swift3 和 Xcode8 创建了一个应用程序,并使用 FMDB 作为我的数据库,当它在模拟器上运行时,它可以从 data.db
获取数据,但是当它在模拟器上运行时通用设备(这是我的手机),tableView 中没有数据,也无法插入记录.我在我的项目中添加了 data.db
,但是当我在模拟器上更改记录时,data.db
中的记录没有改变,但是我打印了路径,它指向模拟器文件夹,该文件夹中的数据库会随着模拟器中的修改而改变,并且该文件夹的路径几乎每次都会改变.我很困惑,是不是因为我实际上没有连接到我的数据库?
I've created an app using Swift3 and Xcode8, and using FMDB as my database, when it runs on the simulator it can get the data from data.db
,but when it runs on the generic device (which is my phone), there's no data in the tableView, also could't insert records. I added data.db
into my project, but when I changed records on simulator, records in data.db
didn't change, but I printed the path, it pointed to simulator folder, database in that folder will changed along the modify in simulator and that folder's path changes almost every time. I'm so confused, is that because I didn't connected to my database in fact?
这里是 Utility.Swift
,它包含常见且经常重用的函数
Here's the Utility.Swift
which holds common and often reused function
import UIKit
class Utility: NSObject {
class func getPath(_ fileName: String) -> String {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendingPathComponent(fileName)
print(fileURL.path)
return fileURL.path
}
class func copyFile(_ fileName: NSString){
let dbPath: String = getPath(fileName as String)
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: dbPath) {
let documentsURL = Bundle.main.resourceURL
let fromPath = documentsURL!.appendingPathComponent(fileName as String)
var error : NSError?
do {
try fileManager.copyItem(atPath: fromPath.path, toPath: dbPath)
}
catch let error1 as NSError {
error = error1
}
let alert: UIAlertView = UIAlertView()
if (error != nil) {
alert.title = "Error Occured"
alert.message = error?.localizedDescription
}
else {
alert.title = "Successfully Copy"
alert.message = "Your database copy successfully"
}
alert.delegate = nil
alert.addButton(withTitle: "Ok")
alert.show()
}
}
class func invokeAlertMethod(_ strTitle: NSString, strBody: NSString, delegate: AnyObject?) {
let alert: UIAlertView = UIAlertView()
alert.message = strBody as String
alert.title = strTitle as String
alert.delegate = delegate
alert.addButton(withTitle: "Ok")
alert.show()
}
}
和 StudentDataBase.swift
包含查询语言
import UIKit
let sharedInstance = StudentDataBase()
class StudentDataBase : NSObject {
var database: FMDatabase? = nil
class func getInstance() -> StudentDataBase{
if((sharedInstance.database) == nil)
{
sharedInstance.database = FMDatabase(path: Utility.getPath("data.db"))
}
return sharedInstance
}
func addStuData(_ student: Student) -> Bool{
sharedInstance.database!.open()
let isInserted = sharedInstance.database!.executeUpdate("INSERT INTO [Student info] (StudentID, FirstName, LastName, PhoneNumber) VALUES (?, ?, ?, ?)", withArgumentsIn: [student.studentID, student.fstName, student.lstName, student.phoneNum])
sharedInstance.database!.close()
return isInserted
}
func updateStuData(_ student: Student) -> Bool {
sharedInstance.database!.open()
let isUpdated = sharedInstance.database!.executeUpdate("UPDATE [Student info] SET FirstName=?, LastName=?, PhoneNumber=? WHERE StudentID=?", withArgumentsIn: [student.fstName, student.lstName, student.phoneNum, student.studentID])
print(student)
print(isUpdated)
sharedInstance.database!.close()
return isUpdated
}
func deleteStuData(_ student: Student) -> Bool {
sharedInstance.database!.open()
let isDeleted = sharedInstance.database!.executeUpdate("DELETE FROM [Student info] WHERE StudentID=?", withArgumentsIn: [student.studentID])
sharedInstance.database!.close()
return isDeleted
}
func getAllStuData() -> [Student] {
sharedInstance.database!.open()
let resultSet: FMResultSet! = sharedInstance.database!.executeQuery("SELECT * FROM [Student info]", withArgumentsIn: nil)
var marrStudentInfo : [Student] = []
if (resultSet != nil) {
while resultSet.next() {
let student : Student = Student()
student.studentID = resultSet.string(forColumn: "StudentID")
student.fstName = resultSet.string(forColumn: "FirstName")
student.lstName = resultSet.string(forColumn: "LastName")
student.phoneNum = resultSet.string(forColumn: "PhoneNumber")
marrStudentInfo.append(student)
}
}
sharedInstance.database!.close()
return marrStudentInfo
}
}
也在 AppDelegate.swift
中,我写了:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Utility.copyFile("data.db")
return true
}
我是 Swift 和 FMDB 的新手,请解释一下,我会尽力而为.非常感谢!!!!
I'm new to Swift and FMDB, please explain and I'll try my best.Thank you very much!!!!
下载完手机里的内容后,数据库是空白的.在我扔掉错误后,它显示
After I downloaded the contents in my phone and the database is blank. And after I throwaway the error, it shows
Inserted failed:Optional("no such table: Student info")
推荐答案
SQLite 提供了很好的错误报告,您应该好好利用它.因此,例如,如果这些 executeUpdate
调用中的任何一个失败,您应该检查 lastErrorMessage
(在关闭数据库之前),以便您知道失败的原因.
SQLite offers good error reporting and you should avail yourself of it. So, for example, if any of these executeUpdate
calls fail, you should examine the lastErrorMessage
(before you close the database) so you know why it failed.
就个人而言,我建议使用 executeQuery(_:values:)
和 executeUpdate(_:values:)
而不是 executeQuery(_:withArgumentsIn:)
和 executeUpdate(_:withArgumentsIn:)
因为前一种方法会抛出错误(从更被动的错误处理范式转变为更主动的错误处理范式,您必须手动记住检查错误).但不管你如何处理错误,都要去做,否则我们都在猜测.
Personally, I'd suggest using executeQuery(_:values:)
and executeUpdate(_:values:)
rather than executeQuery(_:withArgumentsIn:)
and executeUpdate(_:withArgumentsIn:)
because the former methods throw errors (which shifts to a more active error handling paradigm from the more passive one in which you have to manually remember to check for errors). But regardless of how you do your error handling, do it, or else we're all guessing.
就个人而言,我建议使用 Xcode 的设备"窗口并下载您的应用程序包(请参阅 https://stackoverflow.com/a/38064225/1271826) 并查看数据库.我敢打赌,这是一个完全没有定义表的空白数据库.至于原因,可能是因为您之前进行了一些测试,并且 Documents 文件夹中有旧版本的数据库.尝试从设备中彻底删除该应用并重新运行,看看是否能解决问题.
Personally, I'd suggest using Xcode's "Devices" window and download your app's bundle (see https://stackoverflow.com/a/38064225/1271826) and look at the database. I bet it's a blank database with no tables defined at all. In terms of why, it could be because you did some earlier testing and there's an old version of the database in the Documents folder. Try completely deleting the app from the device and re-running and see if that fixes it.
其他更模糊的问题来源包括文件名大小写(例如 Data.db
与 data.db
).macOS 文件系统通常会优雅地处理它,因为它(通常)不区分大小写.但 iOS 设备区分大小写.
Other, more obscure sources of problem include filename capitalization (e.g. Data.db
vs data.db
). The macOS file system will often handle that gracefully because it's not (generally) case sensitive. But iOS devices are case sensitive.
但是,就像我说的,我们一直在盲目飞行,直到 (a) 您在代码中添加一些错误处理,以便您了解为什么它会失败;(b) 查看设备上的数据库,看看它是什么样子.
But, like I said, we're flying blind until (a) you add some error handling to your code so you can see why its failing; and (b) look at the database on the device to see what it looks like.
这篇关于如何在通用 iOS 设备而不是模拟器上使用 FMDB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!