用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.
}
}
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".
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?