Every column has last columns value. SQLITE DATABASE - ios

i am getting same output for every column in the row.
my output should be like
"jack 1 blast male"
but i get like
"male 1 male male"
every column has last columns value.
my whole code is listed below.
please help i am new into sqlite .
i don't know where i should change the code to make it correct please help .
import UIKit
import SQLite3
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var lab1: UILabel!
var db: OpaquePointer?
var heroList = [Hero]()
#IBOutlet weak var tableViewHeroes: UITableView!
#IBAction func buttonSave(_ sender: UIButton) {
let name = "jack"
let powerRanking = "1"
let power = "blast"
let gender = "Male"
var stmt: OpaquePointer?
let queryString = "INSERT INTO Heroes (name, powerrank, power, gender) VALUES (?,?,?,?)"
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 1, name, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_int(stmt, 2, (powerRanking as NSString).intValue) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 3, power, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 4, gender, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_step(stmt) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting hero: \(errmsg)")
return
}
readValues()
print("Herro saved successfully")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return heroList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "cell")
let hero: Hero
hero = heroList[indexPath.row]
cell.textLabel?.text = hero.id.description + (hero.name?.description)! + (hero.powerRanking.description) + (hero.power?.description)! + (hero.gender?.description)!
return cell
}
func readValues(){
heroList.removeAll()
let queryString = "SELECT * FROM Heroes ORDER BY id DESC LIMIT 1;"
var stmt:OpaquePointer?
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
while(sqlite3_step(stmt) == SQLITE_ROW){
let id = sqlite3_column_int(stmt, 0)
let name = String(cString: sqlite3_column_text(stmt, 1))
let powerrank = sqlite3_column_int(stmt, 2)
let power = String(cString: sqlite3_column_text(stmt, 3))
let gender = String(cString: sqlite3_column_text(stmt, 4))
heroList.append(Hero(id: Int(id), name: String(name), powerRanking: Int(powerrank), power: String(power), gender: String(gender)))
}
self.tableViewHeroes.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("HeroesDatabase.sqlite")
if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
print("error opening database")
}
if sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS Heroes (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(255), powerrank INTEGER, power VARCHAR(255), gender VARCHAR(255))", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
readValues()
}
}

by giving encoding to string will solve problem
if sqlite3_bind_text(stmt, 2, (monthen as NSString).utf8String, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}

Related

How to insert data in SQLite in swift iOS?

I'm very new to SQLite and Swift. I have followed this tutorial https://medium.com/#imbilalhassan/saving-data-in-sqlite-db-in-ios-using-swift-4-76b743d3ce0e
but I want ID to auto-increment by SQLite.
// Model
struct PersonModel {
let firstName: String?
let lastName: String?
let phone: String?
let address: String?
}
// DBManager
import Foundation
import UIKit
import SQLite3
class DBManager
{
init()
{
db = openDatabase()
createTable()
}
let dbPath: String = "myDb.sqlite"
var db:OpaquePointer?
// MARK: - Open DataBase
func openDatabase() -> OpaquePointer?
{
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent(dbPath)
var db: OpaquePointer? = nil
if sqlite3_open(fileURL.path, &db) != SQLITE_OK
{
print("error opening database")
return nil
}
else
{
print("Successfully opened connection to database at \(dbPath)")
return db
}
}
// MARK: - Create Table
func createTable() {
let createTableString = "CREATE TABLE IF NOT EXISTS person(id INTEGER PRIMARY KEY AUTOINCREMENT, firstName TEXT, lastName TEXT, phone TEXT, address TEXT);"
var createTableStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK
{
if sqlite3_step(createTableStatement) == SQLITE_DONE
{
print("person table created.")
} else {
print("person table could not be created.")
}
} else {
print("CREATE TABLE statement could not be prepared.")
}
sqlite3_finalize(createTableStatement)
}
// MARK: - Insert
func insert(firstName: String, lastName: String, phone: String, address: String)
{
let insertStatementString = "INSERT INTO person (id, firstName, lastName, phone, address) VALUES (?, ?, ?, ?, ?);"
var insertStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
sqlite3_bind_text(insertStatement, 1, (firstName as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 2, (lastName as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 3, (phone as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 4, (address as NSString).utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT statement could not be prepared.")
}
sqlite3_finalize(insertStatement)
}
// MARK: - Read
func read() -> [PersonModel] {
let queryStatementString = "SELECT * FROM person;"
var queryStatement: OpaquePointer? = nil
var psns : [PersonModel] = []
if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
while sqlite3_step(queryStatement) == SQLITE_ROW {
let id = sqlite3_column_int(queryStatement, 0)
let firstName = String(describing: String(cString: sqlite3_column_text(queryStatement, 1)))
let lastName = String(describing: String(cString: sqlite3_column_text(queryStatement, 2)))
let phone = String(describing: String(cString: sqlite3_column_text(queryStatement, 3)))
let address = String(describing: String(cString: sqlite3_column_text(queryStatement, 4))) // this is where i'm getting error: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
psns.append(PersonModel(firstName: firstName, lastName: lastName, phone: phone, address: address))
print("Query Result:")
print("\(id) | \(firstName) | \(lastName) | \(phone) | \(address)")
}
} else {
print("SELECT statement could not be prepared")
}
sqlite3_finalize(queryStatement)
return psns
}
// MARK: - Delete
func deleteByID(id:Int) {
let deleteStatementStirng = "DELETE FROM person WHERE Id = ?;"
var deleteStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, deleteStatementStirng, -1, &deleteStatement, nil) == SQLITE_OK {
sqlite3_bind_int(deleteStatement, 1, Int32(id))
if sqlite3_step(deleteStatement) == SQLITE_DONE {
print("Successfully deleted row.")
} else {
print("Could not delete row.")
}
} else {
print("DELETE statement could not be prepared")
}
sqlite3_finalize(deleteStatement)
}
}
// ViewController
class ViewController: UIViewController {
#IBOutlet weak var txtFirstName: UITextField!
#IBOutlet weak var txtLastName: UITextField!
#IBOutlet weak var txtPhoneNumber: UITextField!
#IBOutlet weak var txtAddress: UITextField!
#IBOutlet weak var btnSave: UIButton!
var db: DBManager = DBManager()
var persons: [PersonModel] = []
override func viewDidLoad() {
super.viewDidLoad()
}
func setUpDataBase() {
db.insert(firstName: txtFirstName.text ?? "", lastName: txtLastName.text ?? "", phone: txtPhoneNumber.text ?? "", address: txtAddress.text ?? "")
persons = db.read()
}
// MARK: - Button Save Event
#IBAction func btnSave_Event(_ sender: UIButton) {
setUpDataBase()
}
}
when I insert data in SQLite, in func read(), line:
let address = String(describing: String(cString: sqlite3_column_text(queryStatement, 4)))
is throwing error:
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value.
I'm adding value in address textField and still getting this error, also I have no idea if this is right approach for auto-increment ID. could anyone help me out ?
UPDATE
as per #Joakim Danielson suggestion I solved the issue:
// MARK: - Insert
func insert(firstName: String, lastName: String, phone: String, address: String)
{
let insertStatementString = "INSERT INTO person (firstName, lastName, phone, address) VALUES (?, ?, ?, ?);"
var insertStatement: OpaquePointer? = nil
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
sqlite3_bind_text(insertStatement, 1, (firstName as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 2, (lastName as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 3, (phone as NSString).utf8String, -1, nil)
sqlite3_bind_text(insertStatement, 4, (address as NSString).utf8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT statement could not be prepared.")
}
sqlite3_finalize(insertStatement)
}
// MARK: - Read
func read() -> [PersonModel] {
let queryStatementString = "SELECT * FROM person;"
var queryStatement: OpaquePointer? = nil
var psns : [PersonModel] = []
if sqlite3_prepare_v2(db, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
while sqlite3_step(queryStatement) == SQLITE_ROW {
let id = sqlite3_column_int(queryStatement, 0)
let firstName = String(describing: String(cString: sqlite3_column_text(queryStatement, 1)))
let lastName = String(describing: String(cString: sqlite3_column_text(queryStatement, 2)))
let phone = String(describing: String(cString: sqlite3_column_text(queryStatement, 3)))
let address = String(describing: String(cString: sqlite3_column_text(queryStatement, 4)))
psns.append(PersonModel(id: Int(id), firstName: firstName, lastName: lastName, phone: phone, address: address))
print("Query Result:")
print("\(id) | \(firstName) | \(lastName) | \(phone) | \(address)")
}
} else {
print("SELECT statement could not be prepared")
}
sqlite3_finalize(queryStatement)
return psns
}
You should not include the id attribute in your SQL insert statement since it will be automatically handled by the db engine. So change your insert statement to
let insertStatementString = "INSERT INTO person (firstName, lastName, phone, address) VALUES (?, ?, ?, ?);"
When I did this I could run your database related code in a playground and reading values successfully without any runtime error. If you are still getting Unexpectedly found nil while implicitly unwrapping an Optional value error then there is something else that is incorrect, perhaps related to your view controller.
I would recoomend to use Swift package manager to install SQlite3 module by writing the following to your package file:
// Package.swift
dependencies: [
.package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1")
]
Build your project: $ swift build
Using a third-party library to manage your database is a common way to access data stored in a Database, it allow you to perform any operation (insert, read, delete) without using string statements, this through by differents methods such as Table, prepare, insert, filter, etc... One of the key features is that you can set different types of fields depending on your data (string, numbers, datetime, arrays) and create any required model structure.
struct PersonModel {
let firstName: String?
let lastName: String?
let phone: String?
let address: String?
}
import Foundation
import UIKit
import SQLite3
class DBManager
{
init()
{
db = openDatabase()
createTable()
}
let dbPath: String = "myDb.sqlite"
var db:OpaquePointer?
func openDatabase() -> OpaquePointer?
{
let fileURL = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
var db = try? Connection(dbPath)
}
func createTable() {
let createTableString = Table("person")
let id = Expression<Int64>("id")
let firstName = Expression<String?>("firstname")
let lastName = Expression<String>("lastname")
let phone = Expression<String>("phone")
let address = Expression<String>("address")
try! db?.run(users.create(ifNotExists: true, block: { (table) in
table.column(id, primaryKey: true)
table.column(firstName)
table.column(lastName)
table.column(phone, unique: true)
table.column(address)
}))
}
func insert(firstName: String, lastName: String, phone: String, address: String, person: Table)
{
let insert = person.insert("firstname" <- firstName, "lastname" <- lastName, "phone" <- phone, "address" <- address)
let rowid = (try! db?.run(insert))!
}
func read(person: Table) -> [PersonModel] {
var psns : [PersonModel] = []
for user in (try! db?.prepare(person))! {
print("Query :id: \(user[id]), name: \(user[firstname]), second name: \(user[lastname]), phone: \(user[phone]), address: \(user[address])")
}
return psns
}
func deleteByID(id:Int, person: Table) {
try! db?.run(person.filter(id).delete())
}
}
note: method used to create a database table createTable is equivalent to this sentence
CREATE TABLE IF NOT EXISTS "users" (
"id" INTEGER PRIMARY KEY NOT NULL,
"firstname" TEXT,
"lastname" TEXT
"phone" TEXT NOT NULL UNIQUE
"address" TEXT
)

Search JSON data in tableView swift4

I am trying to show jsondata in to the tableView and search country from the searchBar but getting error in to the textDidChange function.
I want the user to enter three words into the searchBar then tableView will open and search data.
struct country : Decodable {
let name : String
let capital : String
let region : String
}
class ViewController: UIViewController,UISearchBarDelegate {
var isSearch : Bool = false
var countries = [country]()
var arrFilter:[String] = []
#IBOutlet weak var tableview: UITableView!
#IBOutlet weak var searchbar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
tableview.dataSource = self
tableview.delegate = self
searchbar.delegate = self
let jsonurl = "https://restcountries.eu/rest/v2/all"
let url = URL(string: jsonurl)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
do{
self.countries = try JSONDecoder().decode([country].self, from: data!)
}
catch{
print("Error")
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
}.resume()
}
shows error into this part.
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
isSearch = false;
self.tableview.reloadData()
} else {
arrFilter = countries.filter({ (text) -> Bool in
let tmp: NSString = text
let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
return range.location != NSNotFound
})
if(arrFilter.count == 0){
isSearch = false;
} else {
isSearch = true;
}
self.tableview.reloadData()
}
}
}
my table view part
extension ViewController : UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(isSearch){
return arrFilter.count
}
else{
return countries.coun
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if(isSearch){
cell.textLabel?.text = arrFilter[indexPath.row]
}else{
cell.textLabel?.text = countries[indexPath.row].name.capitalized
}
return cell
}
}
First of all do not use NSString in Swift and the Foundation rangeOfString API, use native String and native range(of.
Second of all never check for an empty string and for an empty array with .count == 0. There is isEmpty.
Third of all please name structs and classes with a starting capital letter. struct Country ....
The error occurs because you are filtering Country instances and actually you are looking for its name or its region.
This is a pure Swift version of your code
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
isSearch = false
} else {
arrFilter = countries.filter( $0.name.range(of: searchText, options: .caseInsensitive) != nil }
isSearch = !arrFilter.isEmpty
}
self.tableview.reloadData()
}
If you want to filter for name and region write
arrFilter = countries.filter( $0.name.range(of: searchText, options: .caseInsensitive) != nil
|| $0.region.range(of: searchText, options: .caseInsensitive) != nil }
With this syntax declare arrFilter
var arrFilter = [Country]()
and in cellForRow write
let dataArray = isSearch ? arrFilter : countries
cell.textLabel?.text = dataArray[indexPath.row].name.capitalized
You are getting country object of your array as a string so such an error occured..
Please do as below
var arrFilter:[country] = [country]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if(isSearch){
cell.textLabel?.text = arrFilter[indexPath.row].name.capitalized
}else{
cell.textLabel?.text = countries[indexPath.row].name.capitalized
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
isSearch = false;
self.tableview.reloadData()
} else {
arrFilter = countries.filter({ (country) -> Bool in
let tmp: NSString = NSString.init(string: country.name)
let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
return range.location != NSNotFound
})
if(arrFilter.count == 0){
isSearch = false;
} else {
isSearch = true;
}
self.tableview.reloadData()
}
}
First you can not assign a value type [Country] to [String].For example when assign a arrFilter at that time country.filter always return country type value not a string type.
use below code to helping you,
var countries = [country]()
var arrFilter:[country] = [country]()
inside the viewdidLoad
override func viewDidLoad() {
self.countries.append(country(name: "India", capital: "New Delhi", region: "Asia"))
self.countries.append(country(name: "Indonesia", capital: "Jakarta", region: "region"))
self.countries.append(country(name: "Australia", capital: "Canberra", region: "Austrialia"))
// Do any additional setup after loading the view.
}
And
self.arrFilter = self.countries.filter({ (country) -> Bool in
let temp : NSString = country.name as NSString //or you can use country.capital or country.region
let range = temp.range(of: "ind", options: .caseInsensitive)
print(range.location)
print(range.length)
print(temp)
return range.location != NSNotFound
})
Thanks

How to filter the data in model class and display accurately according to letters not words in table view?

Here I need to place a local search for my model class data that displayed in the table view and I tried to implement the search for that I placed successfully but the search was should be like when I enter the first letter it should filter depending on the first letter, not with th letter in all objects
for example in brand names I am having Fastrack, Microsoft, Dell, apple, fila
if I type f then it should display only fastrack and fila but it displays fastrack,fila and Microsoft which containing f
but I need like when the first letter should be equal to f then it should display fastback and file only not Microsoft and if the second letter equals with any another word then it should display filtered results
Here is my code
var bannerModel = [BrandBanners]()
var searchActive : Bool?
var filteredData = [BrandBanners]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchActive == true {
return filteredData.count
}
else {
return bannerModel.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! superBrandTableViewCell
if searchActive == true {
cell.brandImageView.kf.indicatorType = .activity
let item = filteredData[indexPath.row]
if URL(string: (item.brandImageforMobile)!) != nil {
let resource = ImageResource(downloadURL: URL(string: (item.brandImageforMobile)!)!, cacheKey: item.brandImageforMobile)
cell.brandImageView.kf.setImage(with: resource, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
}
else {
cell.brandImageView.image = #imageLiteral(resourceName: "placeholder")
}
cell.activityIndicator.stopAnimating()
self.activityIndicator.stopAnimating()
}
else {
cell.brandImageView.kf.indicatorType = .activity
let item = bannerModel[indexPath.row]
if URL(string: (item.brandImageforMobile)!) != nil {
let resource = ImageResource(downloadURL: URL(string: (item.brandImageforMobile)!)!, cacheKey: item.brandImageforMobile)
cell.brandImageView.kf.setImage(with: resource, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
}
else {
cell.brandImageView.image = #imageLiteral(resourceName: "placeholder")
}
cell.activityIndicator.stopAnimating()
self.activityIndicator.stopAnimating()
}
return cell
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text == nil || searchBar.text == "" {
self.filteredData = self.bannerModel
} else {
var lowerCase = searchBar.text!
self.filteredData = bannerModel.filter({($0.brand?.lowercased().contains(lowerCase.lowercased()))!})
}
self.searchActive = true
brandTableView.reloadData()
}
You should use hasPrefix Method to achieve this
Example
struct User {
var userName : String = ""
var password : String = ""
}
var array = [User.init(userName:"Test",password:"123456"),User.init(userName:"TEMP",password:"123456"),User.init(userName:"Prashant",password:"123456"),User.init(userName:"Test",password:"123456")]
array = array.filter{$0.userName.hasPrefix("T")} // Observe hasPrefix instead of contains
print(array)
For your code
self.filteredData = bannerModel.filter({($0.brand?.lowercased().hasPrefix(lowerCase.lowercased()))!})
EDIT For Type Safety
self.filteredData = bannerModel.filter({($0.brand ?? "").lowercased().hasPrefix("H".lowercased())}
Hope it is helpful
You can do this:
self.filteredData = bannerModel.filter({($0.brand?.lowercased().hasPrefix(lowerCase.lowercased()))!})

Data is being retrieved as project.model not as elements in swift ios

I am trying to retrieve the data elements from DataTable in SQLite database but when I retrieve the data I am getting the data as myproject.mymodelclass where WidgetData is my model class and myproject is the the name of my project on which I am working here is the snapshot of console
[MyProject.WidgetData, MyProject.WidgetData, MyProject.WidgetData, MyProject.WidgetData]
But I want all the elements of DataTable should be printed in ViewController class.
WidgetData Class
import Foundation
class WidgetData {
var widgetid: Int64?
var widgetname: String = ""
var widgetdescription : String = ""
var widgetform: String = ""
var formid : Int64?
var formname : String = ""
var formdescription : String = ""
var formcategory : String = ""
init(widgetid: Int64) {
self.widgetid = widgetid
}
init(formid: Int64) {
self.formid = formid
}
init(widgetid: Int64, widgetname: String, widgetdescription: String, widgetform: String) {
self.widgetid = widgetid
self.widgetname = widgetname
self.widgetdescription = widgetdescription
self.widgetform = widgetform
}
init(formid: Int64, formname : String, formdescription : String, formcategory : String) {
self.formid = formid
self.formname = formname
self.formdescription = formdescription
self.formcategory = formcategory
}
}
StephencelisDB class
import Foundation
class WidgetData {
var widgetid: Int64?
var widgetname: String = ""
var widgetdescription : String = ""
var widgetform: String = ""
var formid : Int64?
var formname : String = ""
var formdescription : String = ""
var formcategory : String = ""
init(widgetid: Int64) {
self.widgetid = widgetid
}
init(formid: Int64) {
self.formid = formid
}
init(widgetid: Int64, widgetname: String, widgetdescription: String, widgetform: String) {
self.widgetid = widgetid
self.widgetname = widgetname
self.widgetdescription = widgetdescription
self.widgetform = widgetform
}
init(formid: Int64, formname : String, formdescription : String, formcategory : String) {
self.formid = formid
self.formname = formname
self.formdescription = formdescription
self.formcategory = formcategory
}
}
ViewController in which I am retrieving the values
//SQLite start
var dataList = [WidgetData]()
var db: OpaquePointer?
var stmt: OpaquePointer?
var widgetnameV = String()
var widgetdescriptionV = String()
var widgetformV = String()
private var contacts = [WidgetData]()
private var selectedContact: Int?
func formDataSetup() {
let queryString = "INSERT INTO WidgetTable (widgetname, widgetdescription, widgetform) VALUES (?,?,?)"
//preparing the query
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
//binding the parameters
if sqlite3_bind_text(stmt, 1, widgetnameV, -1, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 2, widgetdescriptionV, -1, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
if sqlite3_bind_text(stmt, 3, widgetformV, -1, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding name: \(errmsg)")
return
}
//executing the query to insert values
if sqlite3_step(stmt) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting hero: \(errmsg)")
return
}
}
func readValues(){
//first empty the list of heroes
// heroList.removeAll()
//this is our select query
let queryString = "SELECT * FROM WidgetTable"
//
print(dataList)
//statement pointer
var stmt:OpaquePointer?
//preparing the query
if sqlite3_prepare(db, queryString, -1, &stmt, nil) != SQLITE_OK{
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
return
}
//traversing through all the records
while(sqlite3_step(stmt) == SQLITE_ROW){
let widgetid = sqlite3_column_int(stmt, 0)
let widgetnameC = String(cString: sqlite3_column_text(stmt, 1))
let widgetdescriptionC = String(cString: sqlite3_column_text(stmt, 2))
let widgetformC = String(cString: sqlite3_column_text(stmt, 3))
//adding values to list
dataList.append(WidgetData(widgetid: Int64(Int(widgetid)), widgetname: String(describing: widgetnameC), widgetdescription: String(describing: widgetdescriptionC), widgetform: String(describing: widgetformC)))
print(dataList)
}
}
implement description var to print the class properties
class WidgetData:NSObject
{
var tripId: String
var name: String
init(tripId: String ,name:String)
{
self.tripId = tripId
self.name = name
}
override var description: String
{
return "\(self.tripId) \(self.name)"
}
}
Update
Your problem is that you have more than one init , first I advice isolating the data to other class , or in description check first item in every init and use ! if all the init values are not nil

UITableViewDataSource Method can not be called, Even cursor doesn't get inside those methods on debugging

This is My Class in which Methods for UITableViewDatasource are overrided to have data as 'Email' in Tableview in a single Cell using UITableViewCell as in code. but these methods don't get executed. Will anybody please help me to fix this isseu ?
import UIKit
var operationViewFlag: Int!
class HomeCellView: UITableViewCell
{
#IBOutlet weak var btn_tablecell_Delete: UIButton!
#IBOutlet weak var btn_tablecell_Edit: UIButton!
#IBOutlet weak var lbl_tablecell_Email: UILabel!
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
#IBOutlet weak var TableView_Mainscreen: UITableView!
#IBOutlet weak var lbl_MainScreen_Title: UILabel!
#IBOutlet weak var btn_Mainscreen_Insert: UIButton!
var databasepath:String!
var arrayStudInfo:NSMutableArray!
// viewDidLoad
override func viewDidLoad()
{
operationViewFlag=1
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
lbl_MainScreen_Title.font = UIFont(name: "HelveticaNeue-Bold", size: 20)
btn_Mainscreen_Insert.layer.cornerRadius = 15
btn_Mainscreen_Insert.layer.borderWidth = 1
btn_Mainscreen_Insert.layer.borderColor = UIColor.brownColor().CGColor
// Variable Intialization
arrayStudInfo = NSMutableArray()
// Process for Creating Opening Database
let filemgr = NSFileManager.defaultManager()
let dirpath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docdir = dirpath[0] as String
databasepath = docdir.stringByAppendingString("StudentDataManipulation.sqlite");
if filemgr.fileExistsAtPath(databasepath as String)
{
let contactDB = FMDatabase(path: databasepath as String)
if contactDB == nil
{
print("Error: \(contactDB.lastErrorMessage())")
}
if contactDB.open()
{
let sql_stmt = "CREATE TABLE IF NOT EXISTS StudentData (Name TEXT, Phone TEXT, Email TEXT PRIMARY KEY NOT NULL, Comment TEXT)"
if !contactDB.executeStatements(sql_stmt)
{
print("Error: \(contactDB.lastErrorMessage())")
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
}
//viewWillAppear
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(true)
listAllData()
}
//didReceiveMemoryWarning
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Edit Method
#IBAction func btn_Edit_Clicked(sender: UIButton)
{
operationViewFlag=2
let updateView = self.storyboard?.instantiateViewControllerWithIdentifier("PerformOperation") as! PerformOperation
updateView.strEmail = arrayStudInfo[sender.tag]["Email"] as? String
print("Email to pass = \(updateView.strEmail)")
updateView.dictRecord = (arrayStudInfo[sender.tag] as! NSDictionary)
self.navigationController?.pushViewController(updateView, animated: true)
}
// Delete Method
#IBAction func btn_Delete_Clicked(sender: UIButton)
{
let contactDB = FMDatabase(path: databasepath as String)
let strDelete = arrayStudInfo[sender.tag]["Email"] as? String
if contactDB.open()
{
let deleteSQL = "DELETE FROM StudentData WHERE Email='\(strDelete!)'"
let result = contactDB.executeUpdate(deleteSQL, withArgumentsInArray: nil)
if !result
{
print("Error: \(contactDB.lastErrorMessage())")
}
else
{
print("Deleted Record.")
listAllData()
}
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
contactDB.close()
}
// List All Data
func listAllData()
{
arrayStudInfo.removeAllObjects();
let contactDB = FMDatabase(path: databasepath as String)
if contactDB.open()
{
let filemgr = NSFileManager.defaultManager()
let dirpath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docdir = dirpath[0] as String
databasepath = docdir.stringByAppendingString("StudentDataManipulation.sqlite");
if filemgr.fileExistsAtPath(databasepath as String)
{
let contactDB = FMDatabase(path: databasepath as String)
if contactDB == nil
{
print("Error: \(contactDB.lastErrorMessage())")
}
if contactDB.open()
{
let sql_stmt = "CREATE TABLE IF NOT EXISTS StudentData (Name TEXT, Phone TEXT, Email TEXT PRIMARY KEY NOT NULL, Comment TEXT)"
if !contactDB.executeStatements(sql_stmt)
{
print("Error: \(contactDB.lastErrorMessage())")
}
let SelectQuery = "SELECT * FROM StudentData"
if let results:FMResultSet? = contactDB.executeQuery(SelectQuery, withArgumentsInArray: nil)
{
while results?.next() == true
{
let dictRecord = results?.resultDictionary()
arrayStudInfo.insertObject(dictRecord!, atIndex: arrayStudInfo.count)
print("\nRESULT : \(results?.resultDictionary())")
}
TableView_Mainscreen.reloadData()
}
else
{
print("Recored not found");
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
contactDB.close()
}
else
{
print("Error: \(contactDB.lastErrorMessage())")
}
}
// TableView Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrayStudInfo.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let Cell = tableView.dequeueReusableCellWithIdentifier("CellHome") as! HomeCellView
Cell.lbl_tablecell_Email.text! = arrayStudInfo[(indexPath.row)]["Email"] as! String
print("Your Email : \(Cell.lbl_tablecell_Email.text!)")
Cell.btn_tablecell_Edit.tag=indexPath.row
Cell.btn_tablecell_Delete.tag=indexPath.row
Cell.btn_tablecell_Edit.layer.cornerRadius = 10
Cell.btn_tablecell_Delete.layer.cornerRadius = 10
// btn_Delete_Clicked
Cell.btn_tablecell_Edit.addTarget(self, action: #selector(ViewController.btn_Edit_Clicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
Cell.btn_tablecell_Delete.addTarget(self, action: #selector(ViewController.btn_Delete_Clicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
return Cell
}
}
Did you set delegate and data source to ViewController.
If you are using storyboard, you can control click your tableView to ViewController and set both delegate and data source.
If you want to do it in code, you can do this
TableView_Mainscreen.delegate = self
TableView_Mainscreen.datasource = self
Also you should be using lower camel case to name your variable.

Resources