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

用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

学习是最好的投资!

全員に返信(2)
左手右手慢动作

解決しました! ! !
ページの読み込み時にコードを追加して、読み込み時にテーブルビューがデータベース内の既存のデータベースを表示し、エラーが報告されないようにしてみました。元のコード テーブルにはロード時にデータが表示されない可能性が高く、テーブルにデータがないため、後続の関数は「致命的エラー: インデックスが範囲外です」というエラーを報告します。

リーリー

興味のある方は、どこを改善する必要があるかを教えてください。コード全体の実行中に、変更点をクリックすると、失敗したダイアログ ボックスが表示されます。

いいねを押す +0
洪涛

プロンプトから判断すると、arrStu にアクセスするときに添え字が範囲外になったことがエラーのはずです。arrStu の長さを確認できますか? また、そうでない場合、配列内に存在しない要素にアクセスする必要がある状況がなぜ発生するのでしょうか?

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート