I cannot get the data from the Sqlite database. It doesn't print anything for me. I checked the connection to the db is made and the database contains the data. It gives no error but does not print anything. When I start the app the tableView contains no records.
In console print this:
API call with NULL database connection pointer
misuse at line 139466 of [d24547a13b]
prepare: out of memory
// AppDelegate.swift
import UIKit
import SQLite3
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
DataManager.dataManager.dbOpaquePointer = DataManager.dataManager.openDatabase(dbName: "DB.sqlite")
return true
}
}
// TableWord.swift
import Foundation
class TableWord{
var idword: Int = 0
var word: String = ""
var features: String = ""
var number: Int = 0
init(idword: Int, word: String, features: String, number: Int) {
self.idword = idword
self.word = word
self.features = features
self.number = number
}
}
// DataManager.swift
import UIKit
import SQLite3
class DataManager {
static let dataManager = DataManager()
var dbOpaquePointer: OpaquePointer?
// OPEN
func openDatabase(dbName: String) -> OpaquePointer? {
let documentDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileUrl = documentDirectory?.appendingPathComponent(dbName).relativePath
guard let part1DbPath = fileUrl else {
print("part1DbPath is nil.")
return nil
}
if sqlite3_open(part1DbPath, &dbOpaquePointer) == SQLITE_OK {
print(“Open database in \(part1DbPath)")
return dbOpaquePointer
} else {
print("\(Errors.SQLiteError.openDatabase)")
}
return dbOpaquePointer
}
// SELECT
func selectTableWord() -> [TableWord] {
let querySelectTableWord = "SELECT * FROM tableword;"
var dbOpaquePointer2: OpaquePointer? = nil
var dataTableWord: [TableWord] = []
if sqlite3_prepare_v2(dbOpaquePointer, querySelectTableWord, -1, &dbOpaquePointer2, nil) == SQLITE_OK {
while (sqlite3_step(dbOpaquePointer2) == SQLITE_ROW) {
let idword = sqlite3_column_int(dbOpaquePointer2, 0)
guard let queryResultCol1 = sqlite3_column_text(dbOpaquePointer2, 1) else {
print("\(Errors.SQLiteError.queryNil)")
return dataTableWord
}
let word = String(cString: queryResultCol1)
guard let queryResultCol2 = sqlite3_column_text(dbOpaquePointer2, 2) else {
print("\(Errors.SQLiteError.queryNil)")
return dataTableWord
}
let features = String(cString: queryResultCol2)
let number = sqlite3_column_int(dbOpaquePointer2, 3)
dataTableWord.append(TableWord(idword: Int(idword), word: word, features: features, number: Int(number)))
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(dbOpaquePointer2))
print("\(Errors.SQLiteError.prepare): \(errorMessage)")
}
sqlite3_finalize(dbOpaquePointer2)
return dataTableWord
}
}
// ViewController.swift
import UIKit
import SQLite3
class ViewController: UIViewController, UITextViewDelegate, UITableViewDataSource {
@IBOutlet weak var resultTableView: UITableView!
var db: DataManager = DataManager()
var dataTableWord: [TableWord] = []
override func viewDidLoad() {
super.viewDidLoad()
dataTableWord = db.selectTableWord()
searchTextView.delegate = self
resultTableView.dataSource = self
}
//MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataTableWord.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "idCell1Main1", for: indexPath) as! TableViewCell
cell.cellLabelNumber.text = String(dataTableWord[indexPath.row].idword)
cell.cellLabelTitle.text = dataTableWord[indexPath.row].word
cell.cellLabelSubtitle.text = dataTableWord[indexPath.row].features
return cell
}
}
In viewDidLoad you call
var db: DataManager = DataManager()
Which means you are creating a new instance of DataManager instead of using the instance you created in your app delegate and that has an open database connection
You should always access your database using the static property you have created
let db = DataManager.databaseManager
To avoid mistakes like this you can add a private init to your class
private init() {}
this way you can only access it via DataManager.databaseManager