如果我有一堆链式守卫让我们发表声明,我怎样才能诊断出哪个条件失败了,不能将我的后卫分成多个陈述?
鉴于这个例子:
guard let keypath = dictionary["field"] as? String,let rule = dictionary["rule"] as? String,let comparator = FormFieldDisplayRuleComparator(rawValue: rule),let value = dictionary["value"] else { return nil }
如何判断4个let语句中哪个是失败的并调用了else块?
我能想到的最简单的事情是将语句分成4个连续的保护其他语句,但这感觉不对.
guard let keypath = dictionary["field"] as? String else { print("Keypath Failed to load.") self.init() return nil } guard let rule = dictionary["rule"] as? String else { print("Rule Failed to load.") self.init() return nil } guard let comparator = FormFieldDisplayRuleComparator(rawValue: rule) else { print("Comparator Failed to load for rawValue: \(rule)") self.init() return nil } guard let value = dictionary["value"] else { print("Value Failed to load.") self.init() return nil }
如果我想把它们全部放在一个警卫声明中,我可以想到另一种选择.检查guard语句中的nils可能有效:
guard let keypath = dictionary["field"] as? String,let value = dictionary["value"] else { if let keypath = keypath {} else { print("Keypath Failed to load.") } // ... Repeat for each let... return nil }
我甚至不知道是否会编译,但是我可能会使用一堆if语句或警卫开始.
什么是惯用的Swift方式?
Erica Sadun刚刚写了一篇关于这个话题的好文章.
她的解决方案是使用where子句来填充,并使用它来跟踪哪些保护语句通过.使用诊断方法的每个成功保护条件都会将文件名和行号打印到控制台.最后一次诊断打印语句后的保护条件是失败的.解决方案看起来像这样:
func diagnose(file: String = #file,line: Int = #line) -> Bool { print("Testing \(file):\(line)") return true } // ... let dictionary: [String : AnyObject] = [ "one" : "one" "two" : "two" "three" : 3 ] guard // This line will print the file and line number let one = dictionary["one"] as? String where diagnose(),// This line will print the file and line number let two = dictionary["two"] as? String where diagnose(),// This line will NOT be printed. So it is the one that Failed. let three = dictionary["three"] as? String where diagnose() else { // ... }