【问题标题】:How to handle errors/exceptions in swift如何快速处理错误/异常
【发布时间】:2016-02-26 15:25:05
【问题描述】:

这个标题听起来很笼统,尽管它是一个特定的问题。我只是不知道如何更好地描述它...... 我已经阅读了很多关于 swift 错误处理的内容。但我仍然不知道如何解决这个简单的(至少在 Objective-C 中)任务。 我有一个文本字段,想读出字符串值...而不是将其格式化为Date 值。到目前为止没有问题。但是,如果您输入的值与指定的日期格式不匹配,我会收到一个错误消息(没关系……它的格式不正确)。在这种情况下,我只想保存一个标准值。在 Objective-C 中,我会使用 @try-@catch 循环来完成此操作。 swift 中不再存在这种异常处理了吗? 这是我的(Swift 2)代码。希望有人能解答。

func getDateFromTextfield() throws -> NSDate
{
    let formatter:NSDateFormatter = NSDateFormatter()
    formatter.dateFormat = "dd.MM.yyyy"
    formatter.timeZone = NSTimeZone(name: "UTC")

// Here should be a "throw expression" but I dont know how to set it. 

    let date = formatter.dateFromString(dictOfLabelsAndText["Birthdate"] as! String)!

    return date
}

do
{
    child.birthdateAT = try self.getDateFromTextfield()
}
catch {
    child.birthdateAT = formatter.dateFromString("01.01.2000")
    print("wrong date") //Or whatever error
}

【问题讨论】:

  • 另外,如果您可能没有有效的生日,而不是存储 2000 年 1 月 1 日,我可能会建议定义 birthdateAT 以便它是可选的。将未知生日表示为 nil1/1/2000 好得多。

标签: swift error-handling nsdate


【解决方案1】:

Swift do-try-catch 语法旨在处理类似于 Objective-C 中的 NSError 模式的错误,而不是用于处理致命错误/异常。不要被 Swift 的错误处理 do-try-catch 与完全不同的 Objective-C 异常处理模式 @try-@catch 的相似性所迷惑。

只有在确定它们不可能失败时,才应该使用强制展开 (!) 和强制类型转换 (as!)。如果它们可能失败(如本例),您应该优雅地检测到这种情况并相应地处理它。

例如,您可以使用 Swift 错误处理来传达将字符串转换为日期的失败(然后在调用它时使用 do-try-catch 模式以检测和处理它错误):

enum DateError: Error {
    case badDate
    case dateNotFound
}

func getDateFromTextfield() throws -> Date {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy"
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    
    guard let dateString = dictOfLabelsAndText["Birthdate"] as? String else {
        throw DateError.dateNotFound
    }
    
    guard let date = formatter.date(from: dateString) else {
        throw DateError.badDate
    }
    
    return date
}

那么你可以这样做:

do {
    child.birthdateAT = try getDateFromTextfield()
} catch {
    child.birthdateAT = formatter.date(from: "01.01.2000")
}

或者,更简洁地说,使用 try?nil 合并运算符:

child.birthdateAT = try? getDateFromTextfield() ?? formatter.date(from: "01.01.2000")

或者,您可能只是更改方法以返回一个可选项并使用nil 作为检测失败的一种方式:


func getDateFromTextfield() -> Date? {
    let formatter = DateFormatter()
    formatter.dateFormat = "dd.MM.yyyy"
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    
    guard let dateString = dictOfLabelsAndText["Birthdate"] as? String else {
        return nil
    }
    
    return formatter.date(from: dateString)
}

然后做:

if let birthDate = getDateFromTextfield() {
    child.birthdateAT = birthDate
} else {
    child.birthdateAT = formatter.date(from: "01.01.2000")
}

或者,再次使用 nil 合并运算符:

child.birthdateAT = getDateFromTextfield() ?? formatter.date(from: "01.01.2000")

但是,归根结底,除非您知道它永远不可能是 nil,否则不要使用 ! 来解开可选项。否则,请使用可选绑定和/或guard 语句来优雅地检测和报告故障。


这已针对当代版本的 Swift 进行了更新。对于原始 Swift 2 答案,请参阅此答案的 previous revision

【讨论】:

  • 强制解包 (!) 和强制转换 (as!) 会引发运行时错误,不是异常,不是可以“抛出”的内容
  • 我的观点仅仅是 OP 将 Objective-C“异常处理”和 Swift 错误处理混为一谈,并且不能使用catch 来处理因强制展开或强制类型转换而引起的故障。我已尝试相应地简化答案。
  • 很好的答案。我使用第二种可能性来解决问题。尽管如此,“守卫”语句解决方案确实有助于理解 swift 中的错误处理(尽管它比以前复杂得多......:) 谢谢。
【解决方案2】:

选择你的错误——比如

enum DateError: ErrorType {
    case BadDate
    case Whatever
}

把它扔到你评论的地方

throw DateError.BadDate

【讨论】:

    【解决方案3】:

    Swift 3
    我试过了。它有效,但不确定它是否是正确的方法

     enum DateError: Error, CustomStringConvertible {
    
        case badDate
    
        var description: String {
            switch self {
    
            case .badDate:
                return "Error: Invalid date detected."
            }
        }
    
    
    }
    
    
    func convertAMtoDateTime(amTime: String) throws -> String{
    
    
        let fromFormat: String = "hh:mm a"
    
        let toFormat: String = "yyyy-MM-dd hh:mm:ss"
    
        let formatter = DateFormatter()
    
        formatter.dateFormat = fromFormat
    
        let amDate = formatter.date(from: amTime)
    
        let dateTimeFormatter    = DateFormatter()
    
        dateTimeFormatter.dateFormat = toFormat
    
        var dateTime: String = ""
    
        if(amDate != nil){
    
             dateTime = dateTimeFormatter.string(from: amDate!)
    
        }
        else{
    
            throw DateError.badDate
    
        }
    
        return dateTime
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-06
      • 2017-05-25
      • 2013-09-04
      • 2013-11-24
      • 1970-01-01
      • 2015-06-05
      • 2018-12-25
      • 1970-01-01
      相关资源
      最近更新 更多