В AppDelegate
Я вызываю функции в структуре для создания базы данных SQLite и трех таблиц, необходимых для моего приложения. Используя функции в структурах, я вставляю, обновляю, удаляю записи в этих трех таблицах во многих контроллерах представления. Я вставил записи в первую таблицу (таблица сотрудников). Я получаю сообщения о подтверждении печати консоли, и данные заполняются в других табличных представлениях, подтверждающих вставку данных о сотрудниках (для отображения View Controller я перемещаю эти записи таблицы в массив словарей). Работая с QA-тестированием других областей применения, я обнаружил, что в табличном представлении сотрудника для записей сотрудников пусто. Я сделал точки останова, чтобы отладить проблему. Цикл while, который я использую в функции запроса, выходит без данных, которые я только что создал несколько часов назад.
Моя база данных SQLLite создается с сообщением
"Успешно открытое соединение с базой данных в / var / mobile / Containers / Data / Application / BB0FB403-7D26-4837-8BCF-97C23D195717/Documents/MyDatabaseNameHere.sqlite"
Поскольку я потерял данные, в итоге я снова создаю базу данных. Каждый раз, когда я это делаю, я замечал изменения местоположения, например
"Успешно открылась новая база данных в / var / mobile / Containers / Data / Application / CE3F0D84-ED0C-40A2-823A-39E2B8C972BE / Documents/MyDatabaseNameHere.sqlite"
Поэтому я использовал FileManager
классы, чтобы перехватить местоположение и использовать его. Несмотря на это, я все еще теряю данные.
Я провел много исследований по этому вопросу. База данных, кажется, находится в каталоге документов в iPhone, что, как я думаю, ожидается (а не в комплекте). Я подозреваю, что путь к файлу меняется каждый раз, в результате чего приложение пропускает таблицы с данными.
Я предполагаю, что изменение пути к файлу базы данных является причиной проблемы. Я могу ошибаться
Любая помощь приветствуется.
Отредактировано для добавления кода:
Из AppDelegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UserDefaults.standard.register(defaults: [String: AnyObject]())
//if UserDefaults.standard.bool(forKey: "maintenance_identifier") {
// DatabaseClass.deleteRecords()
Thread.sleep(forTimeInterval: 2.0)
// The code below can be commented out after initial creation of DB
// and tables
let initDB = SQLiteDB()
_ = initDB.findFile()
let initEmp = SQLiteEmployees()
_ = initEmp.createEmployeeTable()
_ = initEmp.deleteEmpRecords(inEmpId: nil)
_ = initEmp.createEmployees()
_ = initEmp.queryEmployeeData(in_emp_id: nil)
let initHdr = SQLiteTables()
_ = initHdr.createHeaderTable()
_ = initHdr.createChildTable()
let deleteHdr = SQLiteHeader()
_ = deleteHdr.deleteRecords()
return true
}
структуры и функции
import Foundation
import SQLite3
struct SQLiteDB {
// open Sqlite Database
func openDatabase() -> OpaquePointer?
{
var db: OpaquePointer? = nil
let fileUrl = try!
FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("MailTrackingDatabase2.sqlite")
if sqlite3_open(fileUrl.path, &db) == SQLITE_OK{
print("Successfully opened new database at \(fileUrl.path)")
} else {
print("Unable to open database")
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Error Message = \(errorMessage)")
return nil
}
return db
}
func findFile() -> OpaquePointer? {
var db: OpaquePointer? = nil
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let url = URL(fileURLWithPath: documentsPath)
let fileManager = FileManager.default
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: url.path)!
var db_count = 0
while let element = enumerator.nextObject() as? String {
guard element.hasSuffix(".sqlite")
else { continue }
if db_count > 0 && element.hasSuffix(".sqlite") {
print ("Too Many Databases open at -> \(documentsPath)")
return nil
}
if sqlite3_open(documentsPath + "/" + element, &db) == SQLITE_OK{
print("Found existing database. Successfully opened connection at \(documentsPath + "/" + element)")
db_count += 1
} else {
print("Unable to open database")
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Error Message = \(errorMessage)")
return nil
}
}
if db_count == 0 {
print("going to create new DB")
db = self.openDatabase()
}
return db
}
Запрос данных из таблицы сотрудников:
// Query Employee data from SQLite DB
func queryEmployeeData (in_emp_id: String?) -> (out_emp_id: String, out_email: String, out_first_name: String, out_last_name: String, out_location: String, out_mobile: String, out_work: String, out_site: String ){
var queryEmployeeString: String = " "
if in_emp_id != nil {
queryEmployeeString = "SELECT EMPLOYEE_ID, EMAIL, FIRST_NAME, LAST_NAME, LOCATION, MOBILE, WORK, SITE FROM MT_EMPLOYEES WHERE EMPLOYEE_ID = (?);"
} else {
queryEmployeeString = "SELECT EMPLOYEE_ID, EMAIL, FIRST_NAME, LAST_NAME, LOCATION, MOBILE, WORK, SITE FROM MT_EMPLOYEES;"
}
var empID : String = " "
var emailID : String = " "
var firstName : String = " "
var lastName : String = " "
var location : String = " "
var mobileNum : String = " "
var workNum : String = " "
var siteName : String = " "
let openDB = SQLiteDB()
let db = openDB.findFile()
var queryEmployeeStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, queryEmployeeString, -1, &queryEmployeeStatement, nil) == SQLITE_OK {
if in_emp_id != nil {
sqlite3_bind_text(queryEmployeeStatement, 1, in_emp_id, -1, nil)
}
while (sqlite3_step(queryEmployeeStatement) == SQLITE_ROW) {
let queryResultCol1 = sqlite3_column_text(queryEmployeeStatement, 0)
if queryResultCol1 != nil {
empID = String(cString: queryResultCol1!)
}
print("Employee ID from Query = \(empID)")
let queryResultCol2 = sqlite3_column_text(queryEmployeeStatement, 1)
if queryResultCol2 != nil {
emailID = String(cString: queryResultCol2!)
}
let queryResultCol3 = sqlite3_column_text(queryEmployeeStatement, 2)
if queryResultCol3 != nil {
firstName = String(cString: queryResultCol3!)
}
let queryResultCol4 = sqlite3_column_text(queryEmployeeStatement, 3)
if queryResultCol4 != nil {
lastName = String(cString: queryResultCol4!)
}
let queryResultCol5 = sqlite3_column_text(queryEmployeeStatement, 4)
if queryResultCol5 != nil {
location = String(cString: queryResultCol5!)
}
let queryResultCol6 = sqlite3_column_text(queryEmployeeStatement, 5)
if queryResultCol6 != nil {
mobileNum = String(cString: queryResultCol6!)
}
let queryResultCol7 = sqlite3_column_text(queryEmployeeStatement, 6)
if queryResultCol7 != nil {
workNum = String(cString: queryResultCol7!)
}
let queryResultCol8 = sqlite3_column_text(queryEmployeeStatement, 7)
if queryResultCol8 != nil {
siteName = String(cString: queryResultCol8!)
}
print("SQLiteEmployees: Employee Table Details")
print("Employee Email: \(emailID)")
print("Employee Site Name: \(String(describing: siteName))")
// append values to global array of dictionary
// static var empDict: [String: String] = [:]
// static var arrayEmployees = Array<Dictionary<String, String>>()
AppGlobal.empDict["empid"] = empID
AppGlobal.empDict["email"] = emailID
AppGlobal.empDict["firstname"] = firstName
AppGlobal.empDict["lastname"] = lastName
AppGlobal.empDict["location"] = location
AppGlobal.empDict["mobile"] = mobileNum
AppGlobal.empDict["work"] = workNum
AppGlobal.empDict["site"] = siteName
AppGlobal.arrayEmployees.append(AppGlobal.empDict)
}
print("outside while")
} else {
print ("SQLiteEmployees: Error Preparing Employee Data SQLite Query Statement")
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Error Message = \(errorMessage)")
}
sqlite3_finalize(queryEmployeeStatement)
return (empID, emailID, firstName, lastName, location, mobileNum, workNum, siteName)
}