用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.
}
}
解决啦!!!
我尝试了在页面载入时加入一段代码,让tableview在载入时就显示数据库中已有的数据库,就不会报错了。极有可能是原来代码表格载入时是不显示数据的,这样表格中没有数据,所以后面的函数才会报“fatal error: Index out of range”这个错误。
有兴趣的大神可以帮我看看还有哪里需要改进的地方,整个代码运行时,点击修改点是会弹出不成功的那个对话框!
从提示来看,出错的地方应该是访问 arrStu 时下标越界了, 你检查一下 arrStu 的长度, 有第 n 个元素吗? 另外,如果没有,为什么会导致需要访问一个数组中不存在的元素的情况?