如何定义一个空的、"uninitialized"的键路径并在以后设置它?



我编写了一个程序来计算视图的总宽度/高度(有时我想要总宽度,有时我想要总高度)。唯一的问题是:如果我正在计算宽度,我想在总数中添加一个额外的10。下面是我当前的代码:

func calculateLengthOfAllViews(calculatingWidth: Bool) {
let views = [
UIView(frame: CGRect.zero),
UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50)),
UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
]
var totalLength: CGFloat = 0

if calculatingWidth {
totalLength += 10 /// add extra 10 if calculating width
} else {
totalLength += 0
}

for view in views { /// add each view's width/height
let length: CGFloat
if calculatingWidth {
length = view.frame.width
} else {
length = view.frame.height
}
totalLength += length
}

print("Total length is (totalLength)")
}
calculateLengthOfAllViews(calculatingWidth: true) /// Total length is 160.0
calculateLengthOfAllViews(calculatingWidth: false) /// Total length is 100.0

这很好。但是,我在两个地方重复if calculatingWidth {,以确定:

  1. 是否添加额外的padding
  2. 选择view.frame.width还是view.frame.height作为长度

第二个if语句是不必要的,因为在每次迭代中它的计算结果总是相同的。

所以,我认为键值是可行的——我可以从第一个if语句中存储对.width.height的引用。但是,如何在不"初始化"的情况下定义密钥键呢?它吗?我想这样做:

let keyPath: KeyPath /// Reference to generic type 'KeyPath' requires arguments in <...>
if calculatingWidth {
totalLength += 10
keyPath = UIView.frame.width
} else {
totalLength += 0
keyPath = UIView.frame.height
}
for view in views {
let length = view[keyPath: keyPath] /// Type of expression is ambiguous without more context
totalLength += length
}

然而,这给了我Reference to generic type 'KeyPath' requires arguments in <...>。我该如何解决这个问题?

class KeyPath<Root, Value>

是一个泛型类型,有两个类型参数:根类型和结果值类型,必须在变量声明中指定。在你的例子中应该是

let keyPath: KeyPath<UIView, CGFloat>

有了这个定义,剩下的代码也可以编译。

在函数开始时使用if,在每次循环迭代时使用if。我认为更好的方法是使用reduce(into:_:),以减少条件分支的数量。

代码:

func calculateLengthOfAllViews(calculatingWidth: Bool) {
let views = [
UIView(frame: CGRect.zero),
UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50)),
UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
]
let totalLength: CGFloat
if calculatingWidth {
totalLength = views.reduce(10, { $0 + $1.frame.width })
} else {
totalLength = views.reduce(0, { $0 + $1.frame.height })
}
print("Total length is (totalLength)")
}

相关内容

  • 没有找到相关文章

最新更新