ios - swift管理SQLite数据库,请大神帮忙看看为何总报错“fatal error: Index out of range”。
PHPz
PHPz 2017-04-18 09:04:25
0
2
740

用swift写了一个程序,添加了一个学生成绩管理的sqlite数据库。用的是XCODE7.3.1。
但是总会在labelId.text = "(arrStu[n].id)"处报错“fatal error: Index out of range”。
请大神们帮忙看看代码

import UIKit

class ViewController: UIViewController {
    //数据库结构:主索引  姓名  语文成绩  数学成绩
    struct stu {
        var id:Int32
        var name:String
        var chinese:Int32
        var math:Int32
        init(id:Int32,name:String,chinese:Int32,math:Int32) {
            self.id = id
            self.name = name
            self.chinese = chinese
            self.math = math
        }
    }
    
    /*定义变量*/
    var arrStu:Array<stu> = []//存储数据库的数组
    var db:COpaquePointer = nil
    var statement:COpaquePointer = nil
    var sql:NSString = ""//SQL指令
    var currentStu = 0//当前数据
    
    @IBOutlet var labelId: UILabel!//显示数据编号
    @IBOutlet var textName: UITextField!//输入姓名
    @IBOutlet var textChinese: UITextField!//输入语文成绩
    @IBOutlet var textMath: UITextField!//输入数学成绩
    @IBOutlet var tableViewSqlite: UITableView!
    @IBOutlet var buttonInsert: UIButton!
    @IBOutlet var buttonWrite: UIButton!

    /*表格的设置*/
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return arrStu.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell",forIndexPath: indexPath) as UITableViewCell
        cell.textLabel?.text = "  姓名:\(arrStu[indexPath.row].name)"
        cell.detailTextLabel?.text = "  编号:\(arrStu[indexPath.row].id)  语文:\(arrStu[indexPath.row].chinese)  数学:\(arrStu[indexPath.row].math)"
        return cell
    }
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
        buttonToggle(true, writeAble: false)
        currentStu = indexPath.row
        showSingle(currentStu)
    }
    
    /*定义对话框*/
    func alertView(alertView:UIAlertView,clickedButtonAtIndex buttonIndex:Int) {
        if alertView.title == "  更新  " {
            switch (buttonIndex) {
            case 0://单击“确定”按钮的处理
                //确定更新数据,更新数据库
                let sqltem1:String = "UPDATE class101 SET s_name ='" + textName.text! + "',s_math=" + textChinese.text!
                let sqltem2:String = ",s_math=" + textMath.text! + "WHERE s_id=" + labelId.text!
                sql = sqltem1 + sqltem2
                statement = nil
                sqlite3_prepare_v2(db, sql.UTF8String, -1, &statement, nil)
                if sqlite3_step(statement) == SQLITE_DONE {
                    alertMsg("  成功  ", msgStr: "  数据库更新成功! ")
                } else {
                    alertMsg("  失败  ", msgStr: "  数据库更新失败! ")
                }
                //更新数组
                arrStu[currentStu].name = textName.text!
                arrStu[currentStu].chinese = Int32(Int(textChinese.text!)!)
                arrStu[currentStu].math = Int32(Int(textMath.text!)!)
                tableViewSqlite.reloadData()
            default:
                break
            }
        } else if alertView.title == "  删除  " {
            switch (buttonIndex) {
            case 0://单击“确定”按钮的处理
                //确定删除数据,更新数据库
                sql = "DELETE FROM class101 WHERE s_id=" + labelId.text!
                statement = nil
                sqlite3_prepare_v2(db, sql.UTF8String, -1, &statement, nil)
                if sqlite3_step(statement) == SQLITE_DONE {
                    alertMsg("  成功  ", msgStr: "  数据库删除成功! ")
                } else {
                    alertMsg("  失败  ", msgStr: "  数据库删除失败! ")
                }
                arrStu.removeAtIndex(currentStu)
                tableViewSqlite.reloadData()
                //数据删除后,显示下一笔
                if currentStu == arrStu.count {
                    currentStu -= 1
                }
                showSingle(currentStu)
            default:
                break
            }
        }
    }
    
    /*创建自定义函数*/
    func showSingle(n:Int) {//显示单笔数据
        labelId.text = "\(arrStu[n].id)"
        textName.text = arrStu[n].name
        textChinese.text = "\(arrStu[n].chinese)"
        textMath.text = "\(arrStu[n].math)"
    }
    
    func buttonToggle(insertAble:Bool,writeAble:Bool) -> Void {
        buttonInsert.enabled = insertAble
        buttonWrite.enabled = writeAble
    }
    
    func alertMsg(titleStr:String,msgStr:String) -> Void {
        let alertView:UIAlertView = UIAlertView(title:titleStr,message: msgStr,delegate: self,cancelButtonTitle: "  确定  ")
        alertView.show()
    }
    
    /*页面载入时*/
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        buttonToggle(true, writeAble: false)
        //第一次执行时将数据库复制到Documents文件夹
        let fm:NSFileManager = NSFileManager()
        db = nil
        let src:String = NSBundle.mainBundle().pathForResource("student", ofType: "sqlite")!
        let dst:String = NSHomeDirectory() + "/Documents/student.sqlite"
        if !fm.fileExistsAtPath(dst) {
            try! fm.copyItemAtPath(src, toPath: dst)
        }
        //连接及打开数据库
        if sqlite3_open(dst, &db) != SQLITE_OK {
            alertMsg("  失败  ", msgStr: "  无法打开数据库! ")
        }
        //逐笔读取数据行
        while sqlite3_step(statement) == SQLITE_ROW {
            let id = sqlite3_column_int(statement, 0)
            let temName = sqlite3_column_text(statement, 1)
            let name = String.fromCString(UnsafePointer<CChar>(temName))
            let chinese = sqlite3_column_int(statement, 2)
            let math = sqlite3_column_int(statement, 3)
            let student:stu = stu(id: id, name: name!, chinese: chinese, math: math)
            arrStu.append(student)//将数据行存入数组
        }
        sqlite3_finalize(statement)
        tableViewSqlite.reloadData()
        showSingle(0)//开始时显示第一笔数据
    }

    /*按键的触发事件*/
    @IBAction func modifyClick(sender: UIButton) {//修改
        let alertModify:UIAlertView = UIAlertView()
        alertModify.title = "  更新  "
        alertModify.message = "  确定要更新数据吗?  "
        alertModify.delegate = self
        alertModify.addButtonWithTitle("  确定  ")
        alertModify.addButtonWithTitle("  取消  ")
        alertModify.show()
    }//更新数据
    
    @IBAction func deleteClick(sender: UIButton) {//删除
        if arrStu.count > 1 {//数据大于1笔才允许删除
            let alertDelete:UIAlertView = UIAlertView()
            alertDelete.title = "  删除  "
            alertDelete.message = "  确定要删除数据吗?  "
            alertDelete.delegate = self
            alertDelete.addButtonWithTitle("  确定  ")
            alertDelete.addButtonWithTitle("  取消  ")
            alertDelete.show()
        } else {
            self.alertMsg("  失败  ", msgStr: "  只有一笔数据时不可删除! ")
        }
    }
    
    @IBAction func insertClick(sender: UIButton) {//新增
        buttonToggle(false, writeAble: true)
        labelId.text = ""
        textName.text = ""
        textChinese.text = ""
        textMath.text = ""
    }
    
    @IBAction func writeClick(sender: UIButton) {//写入
        buttonToggle(true, writeAble: false)
        sql = "INSERT INTO class101 (s_name, s_chinese, s_math) VALUES ('" + textName.text! + "'," + textChinese.text! + "," + textMath.text! + ");"
        statement = nil
        sqlite3_prepare_v2(db, sql.UTF8String, -1, &statement, nil)
        if sqlite3_step(statement) == SQLITE_DONE {
            alertMsg("  成功  ",msgStr:"  数据库新增成功! ")
        } else {
            alertMsg("  失败  ",msgStr:"  数据库新增失败! ")
        }
        let id = Int32(sqlite3_last_insert_rowid(db))
        let name = textName.text
        let chinese = Int32(Int(textChinese.text!)!)
        let math = Int32(Int(textMath.text!)!)
        let student:stu = stu(id:id, name:name!, chinese:chinese, math:math)
        arrStu.append(student)//将数据行存入数组
        tableViewSqlite.reloadData()
        showSingle(arrStu.count - 1)
        currentStu = arrStu.count - 1
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

PHPz
PHPz

学习是最好的投资!

reply all(2)
左手右手慢动作

Solved! ! !
I tried adding a piece of code when the page is loading, so that the tableview will display the existing databases in the database when loading, so that no error will be reported. It is very likely that the original code table does not display data when loading, so there is no data in the table, so the subsequent function will report the error "fatal error: Index out of range".

    /*页面载入时*/
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        buttonToggle(true, writeAble: false)
        //第一次执行时将数据库复制到Documents文件夹
        let fm:NSFileManager = NSFileManager()
        db = nil
        let src:String = NSBundle.mainBundle().pathForResource("student", ofType: "sqlite")!
        let dst:String = NSHomeDirectory() + "/Documents/student.sqlite"
        if !fm.fileExistsAtPath(dst) {
            try! fm.copyItemAtPath(src, toPath: dst)
        }
        //连接及打开数据库
        if sqlite3_open(dst, &db) != SQLITE_OK {
            alertMsg("  失败  ", msgStr: "  无法打开数据库! ")
        }
        let sql:NSString = "SELECT * FROM class101"
        if sqlite3_prepare_v2(db,sql.UTF8String,-1,&statement,nil) != SQLITE_OK {
            let alertView:UIAlertView = UIAlertView(title:"  读取失败  ",message: "  读取数据库失败! ",delegate: self,cancelButtonTitle: "  确定  ")
            alertView.show()
            exit(1)
        }
        arrStu.removeAll(keepCapacity: true)
        //逐笔读取数据行
        while sqlite3_step(statement) == SQLITE_ROW {
            let id = sqlite3_column_int(statement, 0)
            let temName = sqlite3_column_text(statement, 1)
            let name = String.fromCString(UnsafePointer<CChar>(temName))
            let chinese = sqlite3_column_int(statement, 2)
            let math = sqlite3_column_int(statement, 3)
            let student:stu = stu(id: id, name: name!, chinese: chinese, math: math)
            arrStu.append(student)//将数据行存入数组
        }
        sqlite3_finalize(statement)
        tableViewSqlite.reloadData()
        showSingle(0)//开始时显示第一笔数据
    }

Anyone who is interested can help me see where I need to improve. When the entire code is running, clicking on the modification point will pop up the unsuccessful dialog box!

洪涛

Judging from the prompt, the error should be that the subscript went out of bounds when accessing arrStu. Can you check the length of arrStu? Is there an nth element? Also, if not, why would it lead to a situation where I need to access an element that doesn't exist in the array?

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template