首页 > 解决方案 > Xcode sqlite.swift,尝试使用like子句

问题描述

我使用 sql.swift 并成功设置了数据库并设置了一些条目,每个条目都有一个 id、名字 (Fname)、姓氏 (Lname) 和电话号码 (Pnumber)。我试图使用文本字段作为名字和姓氏作为一种搜索操作。每次文本字段的文本更改时,我都想使用 like 子句执行搜索查询,以在 tableview 中显示可能是用户正在查找的数据库条目。

这是两个文本字段中的任何一个文本更改时调用的函数。

@IBAction func textFieldChanged(_ sender: UITextField) {
        var firstNameEntered = true
        var lastNameEntered = true
        let firstName = firstNameTextField.text! + "%"
        let lastName = lastNameTextField.text! + "%"
        if(firstName == "%")
        {
            firstNameEntered = false
        }
        if(lastName == "%")
        {
            lastNameEntered = false
        }
        if(!lastNameEntered && !firstNameEntered)
        {
            return
        }
        if(lastNameEntered && !firstNameEntered)
        {
            for user in try! db.prepare(Customers.filter(Lname.like(lastName)))
                {
                    search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
                }
            searchTableView.reloadData()
            return
        }
        if(!lastNameEntered && firstNameEntered)
        {
            for user in try! db.prepare(Customers.filter(Fname.like(firstName)))
                {
                    search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
                }
            searchTableView.reloadData()
            return
        }
        for user in try! db.prepare(Customers.filter(Lname.like(lastName) && Fname.like(firstName)))
            {
                search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
            }
        searchTableView.reloadData()
        return
    }

在调试器中,它应该正确地进入函数。然而,当它到达查询时,无论输入什么都找不到结果。例如,数据库已经有一个条目(id:1,Fname:Patrick,Lname:Smith,Pnumber:123-456-7890)。然后,当我在名字文本字段中键入 P 时,该函数被调用,并添加了“%”并for user in try! db.prepare(Customers.filter(Fname.like(firstName)))达到了正确的查询。根据 like 子句,第一个数据库条目应该是查询结果的一部分,但不包括在内。关于为什么的任何想法?

我还调用此查询以获取另一个地方的所有条目,并成功返回所有条目

        for user in try! db.prepare(Customers) {
            customers.append("id: \(user[id]), \(user[Fname]) \(user[Lname]), Number: \(user[Pnumber])")
       }

如果需要,这是完整的 ViewController 代码:

import UIKit
import SQLite

class SecondViewController: UIViewController {
    
    var db: Connection!
    let Customers = Table("Customers")
    var customerCount: Int = 0
    let id = Expression<Int64>("Id")
    let Fname = Expression<String>("Fname")
    let Lname = Expression<String>("Lname")t
    let Pnumber = Expression<String>("Pnumber")
    
    var phoneNumberDigits: Int = 0
    var customers:[String] = []
    var search:[String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        databaseTableView.delegate = self
        databaseTableView.dataSource = self
        searchTableView.delegate = self
        searchTableView.dataSource = self
        firstNameTextField.delegate = self
        lastNameTextField.delegate = self

        do {
            let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            let fileUrl = documentDirectory.appendingPathComponent("Customers").appendingPathExtension("sqlite3")
            let db = try Connection(fileUrl.path)
            print("\(fileUrl.path)")
            self.db = db
        } catch {
            print(error)
        }
        print("connected")
        try! db.run(Customers.create(ifNotExists: true) {
            t in
            t.column(id, primaryKey: .autoincrement)
            t.column(Fname)
            t.column(Lname)
            t.column(Pnumber, unique: true)
            t.unique(Fname, Lname)
            print("table created")
            
        })
    }

    @IBOutlet weak var databaseTableView: UITableView!
    @IBOutlet weak var searchTableView: UITableView!
    
    @IBOutlet weak var phoneNumberLabel: UILabel!
    
    @IBOutlet weak var firstNameTextField: UITextField!
    @IBOutlet weak var lastNameTextField: UITextField!
    
    @IBOutlet weak var promptTextView: UITextView!
    
    @IBAction func textFieldChanged(_ sender: UITextField) {
        var firstNameEntered = true
        var lastNameEntered = true
        let firstName = firstNameTextField.text! + "%"
        let lastName = lastNameTextField.text! + "%"
        if(firstName == "%")
        {
            firstNameEntered = false
        }
        if(lastName == "%")
        {
            lastNameEntered = false
        }
        if(!lastNameEntered && !firstNameEntered)
        {
            return
        }
        if(lastNameEntered && !firstNameEntered)
        {
            for user in try! db.prepare(Customers.filter(Lname.like(lastName)))
                {
                    search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
                }
            searchTableView.reloadData()
            return
        }
        if(!lastNameEntered && firstNameEntered)
        {
            for user in try! db.prepare(Customers.filter(Fname.like(firstName)))
                {
                    search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
                }
            searchTableView.reloadData()
            return
        }
        for user in try! db.prepare(Customers.filter(Lname.like(lastName) && Fname.like(firstName)))
            {
                search.append("(id: \(user[id])), \(user[Fname]) \(user[Lname]), \(user[Pnumber])")
            }
        searchTableView.reloadData()
        return
    }
    
    @IBAction func addCustomerButton(_ sender: UIButton) {
        if(firstNameTextField.text == "")
        {
            promptTextView.text += "ERROR: No first name given.\n"
            return
        }
        if(lastNameTextField.text == "")
        {
            promptTextView.text += "ERROR: No last name given.\n"
            return
        }
        if(phoneNumberLabel.text == "")
        {
            promptTextView.text += "ERROR: No phone number given.\n"
            return
        }
        if(phoneNumberDigits != 10)
        {
            promptTextView.text += "ERROR: Invalid phone number given. Please enter a 9 digit number\n"
            return
        }
        insertDB()
        firstNameTextField.text = ""
        lastNameTextField.text = ""
        phoneNumberDigits = 0
        phoneNumberLabel.text = ""
    }
    
    @IBAction func oneButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "1"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func twoButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "2"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func threeButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "3"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func fourButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "4"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func fiveButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "5"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func sixButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "6"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func sevenButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "7"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func eightButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "8"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func nineButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "9"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func zeroButton(_ sender: UIButton) {
        if(phoneNumberDigits != 10)
        {
            if(phoneNumberDigits == 3 || phoneNumberDigits == 6)
            {
                phoneNumberLabel.text! += "-"
            }
            phoneNumberLabel.text! += "0"
            phoneNumberDigits += 1
        }
    }
    
    @IBAction func clearButton(_ sender: UIButton) {
        phoneNumberLabel.text = ""
        phoneNumberDigits = 0
    }
    
    // Helper Functions
    
    func insertDB()
    {
       let phoneNumber = phoneNumberLabel.text?.replacingOccurrences(of: "-", with: "", options:
       NSString.CompareOptions.literal, range: nil)
       do {
           
          /* let rowid = try db.run(Customers.insert( Fname <- "\(String(describing: firstNameTextField.text))", Lname <- "\(String(describing: lastNameTextField.text))", Pnumber <- "\(String(describing: phoneNumber))"))
           */
           print("inserted id: \(String(describing: rowid))")
           
           let customerString = "id: \(String(describing: rowid)), \(String(describing: firstNameTextField.text!)) \(String(describing: lastNameTextField.text!)),  \(String(describing: phoneNumberLabel.text!))"
           
           promptTextView.text += customerString + ", added to database.\n\n"
           
       } catch let Result.error(message, code, statement) where code == SQLITE_CONSTRAINT {
           promptTextView.text += "ERROR: invalid input, constraint failed: \(message), in \(String(describing: statement))\n\n"
       }
       catch let error{
           print("insertion failed: \(error)")
           promptTextView.text += "ERROR: Insertion failed!."
           return
       }
        for user in try! db.prepare(Customers) {
            customers.append("id: \(user[id]), \(user[Fname]) \(user[Lname]), Number: \(user[Pnumber])")
           // id: 1, email: alice@mac.com, name: Optional("Alice")
       }
        databaseTableView.reloadData()
    }
    
    // Touch Events
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
}

extension SecondViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
    }
    
}

extension SecondViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if(tableView == databaseTableView)
        {
            return customers.count
        }
        return search.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = databaseTableView.dequeueReusableCell(withIdentifier: "cell")
        if(tableView == databaseTableView)
        {
            cell?.textLabel?.text = customers[indexPath.row]
        } else { cell?.textLabel?.text = search[indexPath.row] }
        
        return cell!
    }
}

extension SecondViewController: UITextFieldDelegate {
    
    // Text Field Delegate Methods
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    
    func textFieldDidBeginEditing(_ textField: UITextField) {
        textField.keyboardType =  UIKeyboardType.alphabet
    }
}

标签: iosswift

解决方案


推荐阅读