变量不存储给它的东西 - Swift 3

Posted

技术标签:

【中文标题】变量不存储给它的东西 - Swift 3【英文标题】:Variable doesn't store what given to it - Swift 3 【发布时间】:2016-11-23 19:13:08 【问题描述】:

我在将从 SQLite DB 获取的日期存储到 Date Var 时遇到问题,我正在尝试将来自 DB 的日期从 String 转换为 Date 后保存到 ResultTask.AlarmDate

当我尝试从ResultTask.AlarmDate? 中删除? 时,它可以很好地存储数据,但是当我有一个没有警报的任务时,我收到一个错误,因为我想在没有警报时将nil 存储为var ,并尝试了多种其他方法来修复它,但没有任何效果。

我在问题发生后立即设置了一个断点并使用Console 查看数据并感到困惑,导致当我打印我试图存储在 var 中的内容时显示的数据但 var 仍然是 @987654328 @,如下所示。

备注

从 DB 获取数据的代码运行良好,我使用的是 Objective-C FM-Database 库,结果见下面的Console

.toDate() 是我使用的String 的扩展,它的代码在AppDelegate.swift 中,如下所示,它工作得很好。

Task 变量类型是我在Task.swift 文件中创建的,以简化工作,它工作得很好,如下所示。

功能:

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)
                    Tasks.append(ResultTask)
                
                ResultTask = nil
            

            TaskRecorderDB?.close()
         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
(lldb) 

AppDelegate.swift:

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
    

Task.swift:

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

提前致谢。

为@KaraBenNemsi 编辑:

我按照你说的更新.toDate()

& 在任务中我使用了var AlarmDate : Date? 而不是var AlarmDate : Date! = nil(我现在没有使用Task.swift 中的其他提示,因为我需要更改应用程序中的许多其他代码)。

并且使用了ResultTask.AlarmDate = results?.string(forColumn: "Alarm").toDate(),当任务没有警报时,我得到一个fatal error: unexpectedly found nil while unwrapping an Optional value

【问题讨论】:

我强烈建议清理(部分矛盾的)问号和感叹号的混乱。如果一个属性应该有一个值,则将其视为非可选的,否则视为真正的可选。声明为隐式展开的可选属性是最糟糕的妥协。 @vadian 我不擅长,我讨厌它,它让我头疼。但我玩了很多次,用它做了很多情况,但大多数情况下它给了我错误,我无法运行应用程序,或者它工作但不像我想要的那样。 据我所知,它仍然在ResultTask.AlarmDate = results?.string(forColumn: "Alarm").toDate() 这一行崩溃。可以发一下string(forColumn: String)函数的代码吗? @KaraBenNemsi 它不是来自我使用的 FMDB 库中的我 @AbdulrahmanAlattas 你确定你在这行ResultTask.AlarmDate = results?.string(forColumn: "Alarm").toDate() 的末尾漏掉了!。你可以试试这条线ResultTask.AlarmDate = results?.string(forColumn: "Alarm")?.toDate() 【参考方案1】:

尝试在任务类中更改这一行,因为它可以是可选的

从这里

var AlarmDate: Date! = nil

到这里

var AlarmDate: Date?

然后用这条线设置闹钟

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

另外,变量名通常应该以小写字母开头。

我也认为这条线是不必要的。你可以省略那行。

ResultTask = nil

请将扩展名也改为

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
   

也许可以尝试更多地了解选项的工作原理 https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

补充: 你的课堂任务也应该看起来更像下面。但是你也必须在其他地方更改代码。它还强制您在初始化任务对象时在构造函数中传递所有必需的参数。

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
    

这里还有一个 Swift 风格指南的链接:

https://github.com/raywenderlich/swift-style-guide

【讨论】:

它在有警报时工作,但是当任务没有警报时它会给我fatal error: unexpectedly found nil while unwrapping an Optional value 错误。 我希望 var 在没有警报时为 nil 使用上面的代码,如果没有设置日期,对象 AlarmDate 的 var AlarmDate 将为 nil 在这一行ResultTask.AlarmDate = results?.string(forColumn: "Alarm").toDate(),但没有?标记它不能为零,对吗?没有警报时我希望它为零。 我在警戒线expect 'else' after 'guard' condition 中收到错误,但它仍在运行!【参考方案2】:

改变你的任务来拥有这个

var AlarmDate : Date?

然后这样做

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

如果在解包结果时发现任何 nil,您将不会设置 ResultTask.AlarmDate 的值。

【讨论】:

对不起@KaraBenNemsi,我只是想我可以在 if-let 上提供一点帮助。随着您对 toDate() 函数的更新(在我回答时它还不存在),一切都会奏效。 没问题 ;-) @JeanSandrin 时机不对。但是发问者无论如何都需要复习可选项 是的,完全同意。我只想说您应该使用链接更新您的答案,以了解有关选项的更多信息,但您已经这样做了;) 有警报时工作,没有警报时我在if let alarm = results?.string(forColumn: "Alarm").toDate() 行中收到fatal error: unexpectedly found nil while unwrapping an Optional value 错误我试过if (results?.string(forColumn: "Alarm").toDate() != nil) 还是一样 @AbdulrahmanAlattas 请查看我的更新答案并更新您的 toDate() 函数

以上是关于变量不存储给它的东西 - Swift 3的主要内容,如果未能解决你的问题,请参考以下文章

Java:类类型变量

Swift 数据类型

如何在编辑内容并将javascript变量传递给它的新输入字段后将Django“forms.ModelForm”保存在数据库中

如何判断 Swift 中实例变量的类是啥

SQL:根据变量选择动态列名

存储对已删除 NSManagedObject 的引用的局部变量会发生啥