I made a program to calculate the total width/height of views (sometimes I want the total width, sometimes I want the total height). The only catch is: If I'm calculating the width, I want to add an extra 10
to the total. Here's my current code:
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
This works fine. But, I'm repeating if calculatingWidth {
in 2 places, to determine:
- Whether to add extra padding 10 padding
- Whether to use
view.frame.width
orview.frame.height
as the length
The second if-statement is unnecessary, because it always evaluates to the same thing in every iteration.
So, I think keypaths are the way to go -- I can store a reference to either .width
or .height
from the first if-statement. However, how do I define a keypath without "initializing" it? I would like to do something like this:
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
}
However, this gives me Reference to generic type 'KeyPath' requires arguments in <...>
. How can I fix this?
is a generic type with two type parameters: the root type and the result value type, and those must be specified in the declaration of the variable. In your case it would be
With that definition, the remaining code compiles as well.