Yesterday came a slew of updates from the mothership. One of them was Xcode 7.3 with Swift 2.2 onboard. Some capabilities have been included in Swift 2.2 that will produce some deprecation warnings. Let’s dig into some of it.
Traditional C-style for loops are deprecated
I’ve been using these forever, so the change will be a little hard – but the alternative is fine.
Deprecated:
for var i = 1; i <= 10; i += 1 { print("\(i)") }
Replace with a range like this:
for i in 1...10 { print("\(i)") }
If you’ve ever gone in reverse to loop – say the end of an array or something, you’ll have to modify your code a bit. You can’t have a range where the start of the range is higher than the end. So do this:
for i in (1...10).reverse() { print("\(i)") }
Or you can also just use enumeration:
let array = [1...10] for number in array { print("\(number)") }
Hello removeFirst()
Arrays had removeLast() but now also have removeFirst(). Don’t call it on an empty array because you will crash.
Comparing tuples (up to 6 elements)
A tuple is a comma separated list of values.
let foo = ("Rush","band") let bar = ("Grace Under Pressure", "album") if foo == bar { print("match") } else { print("nope") }
Selectors as strings deprecated
When you have selectors represented as strings, you can’t have typos that don’t get picked up by the compiler until it’s too late and you get a runtime bomb.
let foo = UIButton() foo.tag = 10 foo.addtarget(self, action: #selector(someFunc), forControlEvents: .TouchUpInside) foo.frame = CGRect(x:10, y:10, width:100, height:20) self.view.addSubview(foo) func someFunc(sender:UIButton){ print(sender.tag) }
Okay wait… I just installed the new Xcode and saw this suggestion, which now makes sense to me.
myButton.addTarget(self, action: "selected:", forControlEvents: .TouchUpInside) //above shows fixable warning. //Changes to this: myButton.addTarget(self, action: #selector(AudioElement.selected(_:)), forControlEvents: .TouchUpInside) //Scope could be self.selected(_:) or one could //just use selected(_:) but less safe
The AudioElement is the class itself, selected is the function, and the (_:) shows that the button object gets passed with the selector.
Okay, wait again. Reading some more on this. Let’s take a NSNotification example.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didChangePreferredContentSize:", name: UIContentSizeCategoryDidChangeNotification, object :nil) // Instead of above, try: NSNotificationCenter.defaultCenter().addObserver(self, #selector(ClassName.didChangePreferredContentSize(_:)), name: UIContentSizeCategoryDidChangeNotification, object :nil) func didChangePreferredContentSize(notification: NSNotification) { updatePreferredFontAdjustment() }
The observer converted.
Since the instance adding the observer is the observer, we don’t need to include the class name. And because the method that receives the notification has a unique name, you don’t need the parameter keyword either (_:). So it can become
NSNotificationCenter.defaultCenter().addObserver(self, #selector(didChangePreferredContentSize), name: UIContentSizeCategoryDidChangeNotification, object :nil)