在Swift 3中展开Optional值时,意外地发现了nil

时间:2017-04-14 06:36:06

标签: swift3

我有一个时间表应用程序,在将所有内容转换为Swift 3之后,一个特定行引发了一个EXC_BAD_INSTRUCTION错误,指出“在解开一个Optional值时意外发现了nil”

这是代码,最后一行返回错误:

 class CyclicDay {
            enum CyclicDayError: Error {
                case invalidStartDate }
            lazy var baseline: Date! = {
                var components = DateComponents()
                components.day = 27
                components.month = 3
                components.year = 2017
                return Calendar.current.date(from: components)!
            }()
            func dayOfCycle(_ testDate: Date) throws -> Int {
                if let start = baseline {
                    let interval = testDate.timeIntervalSince(start as Date)
                    let days = interval / (60 * 60 * 24)
                    return Int(days.truncatingRemainder(dividingBy: 14)) + 1 }
             throw CyclicDayError.invalidStartDate }}



    override func viewDidLoad() {

        // Do any additional setup after loading the view, typically from a nib.
        let cd = CyclicDay()
        let day = try! cd.dayOfCycle(Date())
        let date = Date()
        let calendar = Calendar.current
        let components = calendar.dateComponents([.hour, .minute], from: date)
        let hour = components.hour
        let minutes = components.minute
        _ = "\(String(describing: hour)):\(String(describing: minutes))"

        let lengthTestHour = "\(String(describing: hour))"
        let lengthTestMinute = "\(String(describing: minutes))"

        let formatter = DateFormatter()
        formatter.dateFormat = "a"
        formatter.amSymbol = "AM"
        formatter.pmSymbol = "PM"

        let dateString = formatter.string(from: Date())

        var finalHour = String()
        if lengthTestHour.characters.count == 1 {
            finalHour = String("0\(String(describing: hour))")
        } else {
             finalHour = "\(String(describing: hour))"
        }
        if lengthTestMinute.characters.count == 1 {
            _ = "0\(String(describing: minutes))"
        } else {_ = minutes }
        let convert = finalHour
        let mTime = Int(convert)


        // mTime * 100 + minutes
        let compTime = mTime! * 100 + minutes! 

2 个答案:

答案 0 :(得分:2)

在Swift 3中,所有日期组件都是可选的,您需要打开选项

public static boolean isEmulator() {
        return Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || Build.MODEL.contains("google_sdk")
                || Build.MODEL.contains("Emulator")
                || Build.MODEL.contains("Android SDK built for x86")
                || Build.MANUFACTURER.contains("Genymotion")
                || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
                || "google_sdk".equals(Build.PRODUCT);
    }

否则你会遇到字符串插值问题。

顺便说一句:你不需要let hour = components.hour! let minutes = components.minute! 只是写一个例子

String(describing

我想知道你为什么要手动手动而不是使用你创建的日期格式化工具。

答案 1 :(得分:1)

问题在于以下两点:

let lengthTestHour = "\(String(describing: hour))"
let lengthTestMinute = "\(String(describing: minutes))"

您认为lengthTestHour会存储"7"之类的值,而lengthTestMinute会有"33"之类的值。但不,lengthTestHours实际上持有"Optional(7)"lengthTestMinutes实际上持有"Optional(33)"

然后,您将lengthTestHour分配给convert并尝试将该Optional(7)内容转换为Int,这显然无法完成。现在mTimenil,你试图强行打开最后一行。 BOOM!

这是因为String(describing:)返回一个可选项。通过执行以下操作可以缩短和修复这两行:

let lengthTestHour = "\(hour!)"
let lengthTestMinute = "\(minute!)"