Abdulrahman Alattas Abdulrahman Alattas - 1 year ago 94
Swift Question

Variable doesn't store what given to it - Swift 3

I'm having trouble with storing a date that I got from SQLite DB into a

Var, I'm trying to save the date coming from DB to the
after converting it from String to Date.

When I tried and deleted the
it stored the data fine, but when I have a task without an alarm I get an error cause I want to store
it the var when there's no alarm, and tried multiple other ways to fix it but nothing work.

I made a break point right after the issue and used the
to see the data and got confused, cause the data shown when I print what I'm trying to store in the var but the var is still
, all shown below.


The code that getting data from DB works fine, I'm using the Objective-C FM-Database library, and result is seen in the

is an extension for
that I use and it code is in
as seen bellow, and it work just fine.

Variable type is something I made in a
file to easy the work, and it work just fine & shown below.

The Function:

func GetTasks() -> [Task]{
var Tasks : [Task] = [Task]()

let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true)
let docsDir = dirPaths[0]
databasePath = (docsDir + "/" + "Tasks.db") as NSString

let TaskRecorderDB = FMDatabase(path: databasePath as String)
if (TaskRecorderDB?.open())! {
let querySQL = "Select * from 'Tasks' ORDER BY Priority DESC"
let results:FMResultSet? = TaskRecorderDB?.executeQuery(querySQL, withArgumentsIn: nil)

while results!.next() {
var ResultTask : Task! = Task()
ResultTask.ID = Int((results?.int(forColumn: "ID"))!)
ResultTask.FileName = results?.string(forColumn: "FileName")
ResultTask.Name = results?.string(forColumn: "Name")
ResultTask.Categorie = Int((results?.int(forColumn: "Categorie"))!)
ResultTask.Priority = Int((results?.int(forColumn: "Priority"))!)
ResultTask.AlarmDate? = (results?.string(forColumn: "Alarm").toDate())!
//Break point
ResultTask.Repeat? = (results?.string(forColumn: "Repeat"))!
ResultTask.Completed = Int((results?.int(forColumn: "Completed"))!).toBool()

if(ResultTask.Completed == false){
ResultTask = nil

} else {
print("Error #DB06: \(TaskRecorderDB?.lastErrorMessage())")

return Tasks


(lldb) print (results?.string(forColumn: "Alarm").toDate())!
(Date) $R0 = 2016-11-23 17:21:00 UTC
(lldb) print ResultTask.AlarmDate
(Date?) $R1 = nil


extension String {
func toDate () ->Date! {
var FinalDate : Date! = nil
if (self != ""){
let DateFormatter : Foundation.DateFormatter = Foundation.DateFormatter()
DateFormatter.locale = Locale.current
DateFormatter.dateFormat = "y-MM-dd_HH-mm-ss"
FinalDate = DateFormatter.date(from: self)!

return FinalDate


import Foundation

class Task : NSObject {
var ID : Int! = nil
var FileName : String! = nil
var Name : String! = nil
var Categorie : Int! = nil
var Priority : Int! = nil
var AlarmDate : Date! = nil
var Repeat : String! = nil
var Expired : Bool! = nil
var Completed : Bool! = nil

Thanks in advance.

Edit for @KaraBenNemsi :

I updates the
as you said.

& in task I used
var AlarmDate : Date?
instead of
var AlarmDate : Date! = nil
(I didn't use you're other tip in
for now cause I'll need to change a lot of other code in the app).

And used
ResultTask.AlarmDate = results?.string(forColumn: "Alarm").toDate()
and I get a
fatal error: unexpectedly found nil while unwrapping an Optional value
in it when the task doesn't have an alarm.

Answer Source

Try to change this line in the task class since it can be optional

from this

var AlarmDate: Date! = nil

to this

var AlarmDate: Date?

And then use this line to set the alarm

ResultTask.AlarmDate = results?.string(forColumn: "Alarm")?.toDate()

Also variable names should usually start with a lowercase letter.

I also think this line is unnecessary. You can just omit that line.

ResultTask = nil

Please also change the extension to

extension String {
func toDate() -> Date? {
    guard self != "" else {
         return nil
    var finalDate: Date?
    let DateFormatter : Foundation.DateFormatter = Foundation.DateFormatter()
    DateFormatter.locale = Locale.current
    DateFormatter.dateFormat = "y-MM-dd_HH-mm-ss"
    finalDate = DateFormatter.date(from: self)
    return finalDate

And maybe try to get more into how optionals work https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

Addition: Your class task should probably also look more like below. But then you have to change code in other places as well. It also forces you to pass all the required parameters in the constructor when initialising the task object.

class Task {
    var id: Int
    var fileName: String
    var name: String
    var category: Int
    var priority: Int
    var alarmDate: Date?
    var repeating: String
    var expired: Bool
    var completed: Bool

     init(id: Int, fileName: String, name: String, category: Int, priority: Int, repeating: String, expired: Bool, completed: Bool) {
        self.id = id
        self.fileName = fileName
        self.name = name
        self.category = category
        self.priority = priority
        self.repeating = repeating
        self.expired = expired
        self.completed = completed

And here is also a link to a Swift style guide:


Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download