swift 中的日期格式化程序崩溃

Date formatter crash in swift

请帮我修改这部分代码,

if let dateVaule = UserDefaults().value(forKey: SplashSeenDate){
            let dateStr  = dateVaule as! String
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            dateFormatter.timeZone = TimeZone.ReferenceType.local
            let date = dateFormatter.date(from:dateStr)
            if Global.sharedInstance.Splashs != nil && Global.sharedInstance.Splashs?.count != 0{

                for (i,splash) in (Global.sharedInstance.Splashs?.enumerated().reversed())!{
                    if !checkTimeStamp(date: splash.create_timestamp,StoredDate: date!){
                        Global.sharedInstance.Splashs?.remove(at: i)
                    }
                }
                print(Global.sharedInstance.Splashs?.count ?? "-1")
            }
        }

老实说,我对日期格式化程序很困惑。 当这个项目启动时,它在

发生崩溃
if !checkTimeStamp(date: splash.create_timestamp,StoredDate: date!){

但是,我无法重现此崩溃...**只有 iOS10 的少数用户发生此崩溃。**请指教,非常感谢!

func checkTimeStamp(date: String!,StoredDate: Date) -> Bool {
    let dateFormatter: DateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    dateFormatter.locale = Locale(identifier:"en_US_POSIX")
    let datecomponents = dateFormatter.date(from: date)

    if (datecomponents! >= StoredDate) {
        return true
    } else {
        return false
    }
}

似乎 splash.create_timestamp 变为 nil,当您传入此函数时 checkTimeStamp。它正在崩溃。您可以通过将 checkTimeStamp 函数内的日期参数更改为可选参数并在函数内部传递之前使用 guard 语句来防止崩溃。

您正在以两种不同的方式将 String 转换为 Date

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone.ReferenceType.local //###Why don't you use `TimeZone.current`?
let date = dateFormatter.date(from:dateStr)

checkTimeStamp(date: String!,StoredDate: Date) -> Bool中:

let dateFormatter: DateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.locale = Locale(identifier:"en_US_POSIX")
let datecomponents = dateFormatter.date(from: date)

在您的情况下,缺少此行对于您的首次转换至关重要

dateFormatter.locale = Locale(identifier: "en_US_POSIX")

您可以找到许多讨论 DateFormatter(或旧文章中的 NSDateFormatter)返回 nil 的文章。

当您使用 DateFormatter"yyyy-MM-dd HH:mm:ss" 等固定格式时,您必须将 locale 设置为 Locale(identifier: "en_US_POSIX")

也许您最好定义一种转换方法(或计算 属性)以将 String 转换为适合您应用要求的 Date,并在您需要的任何地方使用它 StringDate 转换:

extension String {
    var toAppDate: Date? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        dateFormatter.timeZone = TimeZone.current
        dateFormatter.locale = Locale(identifier: "en_US_POSIX") //### <- Do not miss.
        return dateFormatter.date(from: self)
    }
}

通常,您的代码使用了过多的强制解包或强制转换。你可以在不使用任何强制的东西的情况下重写它:

    if
        let dateStr = UserDefaults().string(forKey: SplashSeenDate),
        let date = dateStr.toAppDate,
        let splashes = Global.sharedInstance.Splashs, !splashes.isEmpty
    {
        //### In most cases, `filter` is faster than repeated `remove`.
        Global.sharedInstance.Splashs = splashes.filter {
            checkTimeStamp(date: [=14=].create_timestamp, storedDate: date)
        }
        print(Global.sharedInstance.Splashs?.count ?? "-1")
    }

(假设 create_timestamp 不是可选的,并将参数标签 StoredDate: 重命名为 storedDate:。)