A concise way to not execute a loop now that C-Style for loops are going to be removed from Swift 3?
To do this in a way that works for n < 2, you can use the stride
method.
let startIndex = 2
let endIndex = n
for i in stride(from: startIndex, through: endIndex, by: 1) {
memo.append(memo[i-1] + memo[i-2])
}
How to fix C-style for statement has been removed in Swift 3?
I don't think this can be written using for anymore, but you can use while
loop to get the job done:
var nSize = merkleTree.count
while nSize > 1 {
// loop body
nSize = (nSize + 1) / 2
}
I would expect stride
not to work in this case, because as your error states, you cannot use nSize
as the stride
parameter - nSize
is iterating variable that gets declared based on the range, so you need the range to exist. At least that's my interpretation of the error (I know that theoretically you can generate range based on the previously generated item, but obviously stride
does not work that way).
I believe you can find a way to generate a proper array of values using reduce
(because I was able to, see below, maybe you can make it simpler), or by implementing your own stride
that would accept a closure instead of a step (which would allow you to compute next item based on previous one), but both approaches are more complicated and obscure than using the simple while loop, so I personally prefer the while
loop.
My not so nice reduce implementation (in result it uses an array and not a range, since by looking at NSRange
I don't think you can create a range that does not step by 1):
let merkleTree = [1,2,3,4,5,6,7,8,9]
let numberOfDivisions = Int(log2(Double(merkleTree.count))) + 1
let startValue = merkleTree.count
let nSizes = (0..<numberOfDivisions).reduce([startValue]) { (result, next) -> [Int] in
var newResult = result
newResult.append((result.last! + 1) / 2)
return newResult
}
print(nSizes)
// and now you can for-in it:
for nSize in nSizes {
// ...
}
Fix warning C-style for Statement is deprecated in Swift 3
C-style for
loop has been deprecated in Swift 3. You can continue using it for a while, but they will certainly disappear in the future.
You can rewrite your loop to Swift's style:
for i in 0..<len {
let length = UInt32 (letters.length)
let rand = arc4random_uniform(length)
randomString.appendFormat("%C", letters.characterAtIndex(Int(rand)))
}
Since you don't use i
at all in the loop's body, you can replace it with:
for _ in 0..<len {
// do stuffs
}
c-style for statement deprecated with a twist
Might be best to go with a while loop:
var totalHeight: CGFloat = 0
while totalHeight < 2.0 * Configurations.sharedInstance.heightGame {
// Loop code goes here
totalHeight += backgroundImage.size.height
}
C-Style for loop works fine but changing to Swift for-in causes out of bounds errors
cheese.count
is only being evaluated once. Suppose you start with 3 items in cheese
. The loop will iterate over indices 0
, 1
, 2
. If you remove item 1
, then the old 2
becomes the new 1
, and there is no longer an item at index 2
. However, the loop will continue to index 2
, just as it was set out to do from the beginning.
To fix this, every time you remove, deincrement your index:
for i in 0 ..< cheeses.count {
print(i) //prints just fine every time
if CGRectIntersectsRect(mouse.node.frame, cheeses[i].node.frame) {//throws the out of bounds error
cheeses[i].node.removeFromParent()
cheeses.removeAtIndex(i) //the culprit? ... no longer!
i -= 1 //fixed!
}
}
Now, that solves the error for the solution as you present it, but I propose a cleaner solution:
cheeses.filter{ cheese in
if CGRectIntersectsRect(mouse.node.frame, cheese.node.frame {
cheese.node.removeFromParent()
return false //don't keep this cheese
}
else {
return true //keep this cheese
}
}
Replacement for C-style loop in Swift 2.2
Although it's not as "pretty", you can use stride
:
for var i in 0.stride(to: -1, by: -1) {
print(i)
}
safely remove item while iterating backward in Swift 3
Use stride
:
for i in stride(from: allowedItems.count - 1, through: 0, by: -1) {
}
Swift -How does a for loop finish before the line under it?
Fundamentally all operations are executed sequentially as stated in Oleg's answer.
What you have to understand is that special things like for loop
statements or if statements
or other, are sort of instructions for the runtime. And when the code executtion gets to the point where it encounters for loop
instruction it goes on and on inside of a for loop. It just knows that this thing inside of for loop {}
should be executed n
times before it can continue. So when the for loop finishes, it goes to the next line of code and does whatever instruction is there.
This is not very deep explanation, but I was trying to be simplistic. Hope it helps.
New Swift for-in syntax for incrementing and decrementing loops
Why doesn't the Swift range operator handle decreasing ranges?
I believe I read a statement from a Swift team member (probably @jckarter) that they deliberately designed Range
in this way to avoid a likely source of programmer errors. The reasoning was that more often than not, when you create a range from variables (not literals) like a..<b
, you'd implicitly assume a <= b
. Range
is designed to trap if that assumption is violated to make the (possible) error obvious to you.
I can't find the reference at the moment though.
Related Topics
No Exact Matches in Call to Instance Method Error Message in Swift
How to Use @Fetchrequest Outside a View
Is There Any Difference at All Between Suffix(From:) and Dropfirst(_:)
Swift Nwlistener Listen, Cancel, and Relisten Successfully
Reading from Txt File in Swift 3
How to Create an iOS Liveview in Xcode 8/Swift 3
Window Title Bar Appears Transparent Issue (Not Really Transparent)
Finding The First Non-Repeating Character in a String Using Swift
Accessing an Actor's Isolated State from Within a Swiftui View
Uipangesturerecognizer Is Not Working in iOS 13
Notification in Swift Returning Userinfo in Dictionary
Swift - How to Deal with Uncaught Exception
Navigation Bar Items After Push from Swiftui to UIkit
Shorthand for Wrapping a Swift Variable in an Optional
Get Path of a File in a Data Set Located in Assets.Xcassets
Why Is Swift Counting This Grapheme Cluster as Two Characters Instead of One