变量不存储给它的东西 - 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的主要内容,如果未能解决你的问题,请参考以下文章
如何在编辑内容并将javascript变量传递给它的新输入字段后将Django“forms.ModelForm”保存在数据库中