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

用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

学习是最好的投资!

répondre à tous(2)
左手右手慢动作

Résolu ! ! !
J'ai essayé d'ajouter un morceau de code lors du chargement de la page, afin que la tableview affiche les bases de données existantes dans la base de données lors du chargement, afin qu'aucune erreur ne soit signalée. Il est très probable que la table de codes d'origine n'affiche pas de données lors du chargement, il n'y a donc aucune donnée dans la table, donc la fonction suivante signalera l'erreur « erreur fatale : index hors plage ».

 /*Lors du chargement de la page*/
    remplacer func viewDidLoad() {
        super.viewDidLoad()
        // Effectuez toute configuration supplémentaire après le chargement de la vue, généralement à partir d'une plume.
        boutonToggle (vrai, writeAble : faux)
        // Copiez la base de données dans le dossier Documents lors de la première exécution
        laissez fm:NSFileManager = NSFileManager()
        db = nul
        laissez src:String = NSBundle.mainBundle().pathForResource("student", ofType: "sqlite") !
        laissez dst:String = NSHomeDirectory() + "/Documents/student.sqlite"
        si !fm.fileExistsAtPath(dst) {
            essayez ! fm.copyItemAtPath(src, toPath : dst)
        }
        //Connectez-vous et ouvrez la base de données
        si sqlite3_open(dst, &db) != SQLITE_OK {
            alertMsg("Échec", msgStr : "Impossible d'ouvrir la base de données !")
        }
        laissez sql:NSString = "SELECT * FROM class101"
        if sqlite3_prepare_v2(db,sql.UTF8String,-1,&statement,nil) != SQLITE_OK {
            let alertView:UIAlertView = UIAlertView(title:" Échec de la lecture ", message : " Échec de la lecture de la base de données ! ", délégué : self, cancelButtonTitle : " OK »)
            alertView.show()
            sortie(1)
        }
        arrStu.removeAll (keepCapacity : true)
        //Lire les lignes de données une par une
        while sqlite3_step(statement) == SQLITE_ROW {
            laissez id = sqlite3_column_int (instruction, 0)
            laissez temName = sqlite3_column_text (instruction, 1)
            let name = String.fromCString(UnsafePointer<CChar>(temName))
            laissez chinois = sqlite3_column_int (instruction, 2)
            laissez math = sqlite3_column_int (instruction, 3)
            let student:stu = stu(id: id, name: name!, chinois: chinois, math: math)
            arrStu.append (étudiant) // Enregistrer les lignes de données dans un tableau
        }
        sqlite3_finalize(instruction)
        tableViewSqlite.reloadData()
        showSingle(0)//Afficher les premières données au début
    

Toute personne intéressée peut m'aider à voir où je dois m'améliorer. Lorsque l'intégralité du code est en cours d'exécution, cliquer sur le point de modification fera apparaître la boîte de dialogue qui échoue !

洪涛

À en juger par l'invite, l'erreur devrait être que l'indice est sorti des limites lors de l'accès à arrStu. Pouvez-vous vérifier la longueur de arrStu ? Y a-t-il un nième élément ? De plus, si ce n'est pas le cas, pourquoi cela conduirait-il à une situation dans laquelle je devrais accéder à un élément qui n'existe pas dans le tableau ?

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal