使用 "where" 子句在 Swift 算术中生成可选类型

Using "where" clauses to produce optional types in Swift arithmetic

我想在用户交互期间触发基于某些 UI 关系的条件逻辑(在这种情况下,我想在用户滚动到 UIScrollView 中的某个点时调用一个方法).我希望以下代码行能够合法地执行此操作,因为它非常具有表现力:

func scrollViewDidScroll(scrollView: UIScrollView) {
    guard let overlap = scrollView.contentOffset.y - 220 where overlap > 0 else {
        return
    }

    reactToScrollOverlap(of: overlap)
}

但是,我收到 guard let 需要可选类型的错误。这是合理的,但我预计在这种情况下 where 子句自然会引入一个可选的,因为如果算术运算错误那么就不存在 overlap.

的匹配值

有没有一种方法可以使用 guard let(或者,if let),这样包含的 where 子句就 Int、CGFloat 或其他算法之间的算术结果规定了条件primitive/primitive-like 类型?

guardif let 语句通常只用于解包可选值。我对这个解决方案不是很满意,但您可以将 scrollView.contentOffset.y 转换为 Optional<CGFloat> 以获得您想要的行为:

guard let overlap = scrollView.contentOffset.y - 220 as CGFloat? where overlap > 0 else {
    return
}
guard let value = someOptionalValue {
}

if let value = someOptionalValue {
}

这些是将可选值绑定到变量的方式。如果您使用的是 guard letif let,则您使用的是仅从可选类型获取值。

只有当所有可选值都在 where 子句之前有一个值时,where 子句才会被触发。

我想你想做的是这样的:

let delta = scrollView.contentOffset.y - 220

if delta > 0 {

} else {

}

我更喜欢清晰而不是简洁。

编辑:

我认为这是一个更好的方法:

let yOffset        = scrollView.contentOffset.y
let newOffset:Int? = yOffset > 220 ? yOffset : nil

您在一个表达式中做了 3 件事 - 声明一个变量(常量)、分配它并检查它的值。

在表达式中声明一个变量通常是不受欢迎的,Swift 并没有真正启用它。除了一个例外 - 可选项的展开。您没有解包一个可选的,所以只需将表达式正确地拆分为一个声明和一个比较:

let overlap = contentOffset.y - 220

guard overlap > 0 else {
    return
}

另一种选择是使用 case let 模式。我不是它的忠实粉丝,但它可能是你想要的:

guard case let overlap = contentOffset.y - 220 where overlap > 0 else {
    return
}

print("overlap:", overlap)