1

I've been coding for about 2 years, but I am still terrible at it. Any help would be much appreciated. I have been using the following code to set my background image parameters, after updating to Xcode 7.3 I got the warning 'C-Style statement is deprecated and will be removed':

for var totalHeight:CGFloat = 0; totalHeight < 2.0 * Configurations.sharedInstance.heightGame; totalHeight = totalHeight + backgroundImage.size.height  {...}

Just to clarify, I have looked at a few other solutions/examples, I have noticed that one workaround is to use the for in loop, however, I just can't seem to wrap my head around this one and everything I have tried does not seem to work. Again, any help would be much appreciated.

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
Dan
  • 13
  • 2
  • The question was originally marked as a duplicate of http://stackoverflow.com/questions/36213333/fix-warning-c-style-for-statement-is-deprecated-in-swift-3 but the answer given there will only;y work for simple incrementing fly 1 for loops – JeremyP Apr 15 '16 at 16:15
  • The OP is perfectly right. C-style for loops can do a lot of cool, convenient things that cannot readily be reproduced by any kind of for loop in Swift. In my view, taking C-style for loops away from Swift was terribly ill-advised. – matt Apr 15 '16 at 16:44

2 Answers2

4

A strategy that always works is to convert your for loop into a while loop along the lines of this pattern:

for a; b; c {
  // do stuff
}

// can be written as:

a // set up
while b { // condition
  // do stuff
  c // post-loop action 
}

So in this case, your for loop could be written as:

var totalHeight: CGFloat = 0
while totalHeight < 2.0 * Configurations.sharedInstance.heightGame {
  // totalHeight = totalHeight + backgroundImage.size.height can be
  // written slightly more succinctly as:
  totalHeight += backgroundImage.size.height
}

But you're right, the preferred solution when possible is to use for in instead.

for in is a bit different to the C-style for or while. You don't control the loop variable directly yourself. Instead, the language will loop over any values produced by a "sequence". A sequence is any type that conforms to a protocol (SequenceType) that can create a generator that will serve that sequence up one by one. Lots of things are sequences – arrays, dictionaries, index ranges.

There's a kind of sequence called a stride that you could use to solve this particular problem using for in. Strides are a bit like ranges that increment more flexibly. You specify a "by" value that is the amount to vary by each time around:

for totalHeight in 0.stride(to: 2.0 * Configurations.sharedInstance.heightGame,
                            by: backgroundImage.size.height) {

    // use totalHeight just the same as with the C-style for loop

}

Note, there are two ways of striding, to: (up to but not including, like if you'd used <), and through: (up to and including, like <=).

One of the benefits you get with a for in loop is that the loop variable doesn't need to be declared with var. Instead, each time around the loop you get a fresh new immutable (i.e. constant) variable, which can help avoid some subtle bugs, especially with closure variable capture.

You still need the while form occasionally (for example there's no built-in type that allows you to double a counter each time around), but for much everyday use there's a neat (and hopefully more readable) way of doing it without.

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
1

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
}
Slayter
  • 1,172
  • 1
  • 13
  • 26
  • Yes, it's a pity, but keeping in mind that a for loop can _always_ be unrolled into a while loop is often the best way to solve this. It isn't elegant, but it gets the job done. – matt Apr 15 '16 at 16:45
  • This worked, @Slayter. Using the while loop as a workaround did not cross my mind. I think I was too tired. Much appreciated. – Dan Apr 16 '16 at 05:19