0

I'm using sqlite for my iOS Swift app. Below is an error snippet when I select a row from database.

The problem is: It has a value but it generate a fatal error. (unexpectedly found nil while unwrapping an Optional value)

enter image description here

The library I used is: stephencelis/SQLite.swift

import Foundation
import SQLite

struct studentDB {
    let table = Table("students")
    let code = Expression<String>("code")
    let name = Expression<String>("name")
    let gender = Expression<Int>("gender")
    let birth = Expression<String>("birth")
    let born = Expression<String>("born")
    let className = Expression<String>("class")
    let speciality = Expression<String>("speciality")
    let department = Expression<String>("department")
    let faculty = Expression<String>("faculty")
    let training = Expression<String>("training")
    let course = Expression<String>("course")
    let advisor = Expression<String>("advisor")
}

struct student {
    let code: String!
    let name: String?
    let gender: Int?
    let birth: String?
    let born: String?
    let className: String?
    let speciality: String?
    let department: String?
    let faculty: String?
    let training: String?
    let course: String?
    let advisor: String?
}

class Student {
    class func getStudent(code: String) -> student? {
        let studentDBInfo = studentDB()
        let studentRaw = try! userDatabase.pluck(studentDBInfo.table.filter(studentDBInfo.code == code))
        if (studentRaw != nil) {
            let studentInfo = student(
                code: studentRaw![studentDBInfo.code],
                name: studentRaw![studentDBInfo.name],
                gender: studentRaw![studentDBInfo.gender],
                birth: studentRaw![studentDBInfo.birth],
                born: studentRaw![studentDBInfo.born],
                className: studentRaw![studentDBInfo.className],
                speciality: studentRaw![studentDBInfo.speciality],
                department: studentRaw![studentDBInfo.department],
                faculty: studentRaw![studentDBInfo.faculty],
                training: studentRaw![studentDBInfo.training],
                course: studentRaw![studentDBInfo.course],
                advisor: studentRaw![studentDBInfo.advisor]
            )
            return studentInfo
        } else {
            return nil
        }
    }
}

All other column work fine. To be more clear:

print(studentRaw![studentDBInfo.code]) -> crash 
print(studentRaw![studentDBInfo.name]) -> "Pham Tuan Anh"
Krunal
  • 77,632
  • 48
  • 245
  • 261
  • 2
    Please post your code as text instead of a picture. – mag_zbc Aug 18 '17 at 08:35
  • @mag_zbc I updated. – Phạm Tuấn Anh Aug 18 '17 at 08:41
  • I don't think that `studentRaw` is nil since you are already checking it against nil. Because you have your `student` initialiser on multiple lines, it could be any one of those parameters if the initialiser doesn't handle nil values. I would suggest to print each value before you create `studentInfo` to confirm that you are receiving a value for each one of them – Malik Aug 18 '17 at 08:46
  • Please include the definition of your `studentDB` class – mag_zbc Aug 18 '17 at 08:50
  • @mag_zbc I updated the full file – Phạm Tuấn Anh Aug 18 '17 at 08:53
  • @Malik Thanks for commenting. I tried to "hard set" the value of `code` to `"1"` and it worked fine. That means all other columns worked. – Phạm Tuấn Anh Aug 18 '17 at 08:55
  • 1
    That means that `studentRaw![studentDBInfo.code]` might be returning nil. Put a break point and see the values of `studentRaw` and `studentDBInfo.code` – Malik Aug 18 '17 at 09:02
  • 1
    Also, in your updated code, I can see that all the parameters except `code` are optional. This means that if `studentRaw` was in fact nil, and you hard-coded only `code`, it won't crash – Malik Aug 18 '17 at 09:04
  • @Malik I see. `studentRaw![studentDBInfo.code]` is nil. But I just used `studentDBInfo.code` to compare and get the row. How can it be nil ? – Phạm Tuấn Anh Aug 18 '17 at 09:07
  • 1
    `studentDBInfo.code` can have a value but `studentRaw![studentDBInfo.code]` might not have a value for subscript `studentDBInfo.code`. That is why I said to put a break point and see the current state of `studentRaw` – Malik Aug 18 '17 at 09:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/152233/discussion-between-phm-tun-anh-and-malik). – Phạm Tuấn Anh Aug 18 '17 at 09:16

1 Answers1

1

You are force unwrapping studentRaw, and that's crashing because it's nil. You need to add the following before you try to use it.

guard let studentRaw = studentRaw else {
    // Handle the error
    return
}

As for why code has a value, it looks like you are reusing that variable, so possibly it has been set previously.