我目前在iOS项目中的代码如下所示:
for var i = 0; CGFloat(i) * gridSpacing.width * scale < bounds.width; ++i
我现在收到警告,这个样式for循环将被弃用。我在Stack Overflow和其他地方看到的每个地方都建议使用stride进行复杂的for循环。但是,stride对我没有帮助,因为结束条件不是与另一个整数的简单比较。
如何使用for-in循环快速执行此操作?
注意,我可以循环一个CGFloat,但我想通过重复添加浮点数来避免增量错误。
我也可以使用while循环,但是我在同一个函数中有几个这样的循环,并且为i创建了一个很好的新范围。斯威夫特似乎不喜欢任意新的范围。
编辑:根据@ Sulthan的回答,我创建了一个SequenceType来执行此操作。 IMO,如果要删除for循环,这样的事情应该很快:
struct forgenerator : GeneratorType
{
typealias Element = Int
typealias Condition = (Element) -> Bool
var idx : Element
var condition : Condition
var increment: Element
mutating func next() -> Element? {
if condition(idx)
{
let result = idx
idx += increment
return result
}
return nil
}
}
struct forsequence : SequenceType
{
typealias Generator = forgenerator
var startPoint : Generator.Element
var condition : Generator.Condition
var increment : Generator.Element
func generate() -> Generator {
return forgenerator(idx: startPoint, condition: condition, increment: increment)
}
}
func forgen(start: Int, condition: (Int) -> Bool, increment: Int) -> forsequence
{
return forsequence(startPoint: start, condition: condition, increment: increment)
}
func forgen(start: Int, condition: (Int) -> Bool) -> forsequence
{
return forgen(start, condition: condition, increment: 1)
}
用法:
for i in forgen(0, condition: { CGFloat($0) * self.gridSpacing.width * self.scale < self.bounds.width})
注意,不得不在各处使用self,因为所有这些变量都是一个类的成员。
答案 0 :(得分:1)
总有递归!避免循环,同时仍然允许您处理更改约束。它功能齐全! ; - )
func recursion(currentIndex: Int) {
guard CGFloat(currentIndex) * gridSpacing.width * scale < bounds.width else {
return
}
// do what you need to
recursion(currentIndex + 1)
}
答案 1 :(得分:0)
让我们分步进行:
let itemWidth = gridSpacing.width * scale
for var i = 0; CGFloat(i) < bounds.width / itemWidth; ++i {
}
现在你可以直接
了let itemWidth = gridSpacing.width * scale
let numItems = Int(floor(Double(bounds.width / itemWidth)))
for var i = 0; i < numItems; i++ {
}
或
for i in 0..<numItems {
}
另一种选择是使用while
循环:
(我已经使用了你想要避免的解决方案,但我觉得它仍然更好,并且错误不太可能比scale
引入的错误更重要。)
let itemWidth = gridSpacing.width * scale
var x = 0
var index = 0
while (x < bounds.width) {
// do something
index += 1
x += itemWidth
}
此外,您始终可以将迭代提取到函数中:
func strideOverFloats(start: Int, addition: Int, condition: (CGFloat) -> Bool, _ closure: (Int) -> ()) {
var i = start
while (condition(CGFloat(i))) {
closure(i)
i += addition
}
}
let width: CGFloat = 200
let gridSize: CGFloat = 10
let scale: CGFloat = 2
strideOverFloats(0, addition: 1, condition: { $0 * gridSize * scale < width}) {
print($0)
}
答案 2 :(得分:0)
将其更改为while
循环?
var i: CGFloat = 0
while ((i * gridSpacing.width * scale) < bounds.width) {
// ...
i += 1;
}
答案 3 :(得分:0)
您可以使用while循环完成此操作:
var i: Int = 0
while CGFloat(i) * a * b < bounds.width {
// Your code
i += 1 // ++ is also deprecated
}
我认为他们的意图是,当执行的次数已知时使用for-in
,而while
的条件是可以在循环内修改的变量。{/ {} p>
您还可以在for-in
中使用条件中断语句,但while
似乎更清晰。
答案 4 :(得分:0)
我还建议更快捷的风格:
for index in 0..<gridSpacing.width * scale {
// Your code here
}
答案 5 :(得分:0)
我刚刚发现for-in循环有一个where
子句!!
用法示例:
var end: CGFloat = bounds.width
for i in 0..<(Int(end+1)) where CGFloat(i) * gridSpacing.width * scale < CGFloat(end) {
print(i)
}