Swift "pitfalls"
2017-03-16: Updated for Swift 3.0
I’ve been doing iOS and Mac OS programming in Swift for a while and I noticed some “pitfalls”. They are some syntax details that may cause compiler errors and leave you wonder, “why is that”. I believe that all the “pitfalls” here are included in the Swift official documentation and tutorials already. But I think it would help myself and other people if I put them all together here in one place.
1. Naming of methods
The following code won’t work:
class TestClass {
class func print(_ string: String) {
print("Test: \(string)")
// The above line will call itself i.e. `TestClass.print(_:)`
// instead of `print(_:separator:terminator:)` in Swift Standard Library
// leading to an infinite cycle
}
init() {
TestClass.print("init")
}
}
Fix:
class func print(_ string: String) {
Swift.print("Test: \(string)")
}
2. Exposing method to Objective-C
In Swift 3.0, the following code won’t compile:
// Does not work
class TestClass { // Not a subclass of `NSObject`
func setUp() {
button.addTarget(
self,
action: #selector(buttonTapped(_:)),
for: .touchUpInside)
}
private func buttonTapped(sender: Any) { // Private
}
}
Error message would be Argument of '#selector' refers to instance method 'buttonTapped' that is not exposed to Objective-C'
Fix by adding @objc
to the method:
class TestClass {
@objc private func buttonTapped(sender: Any) {
}
}
Thanks to reader Jon Showing for their input.
3. Single line expression in closures: Implicit ‘return’
func moveViewsToCenter() {
}
func makeViewsVisible() -> Bool {
}
func performAnimation() {
// Works!
let animationsA = { () -> Void in
self.moveViewsToCenter()
}
// Swift 2.3: Won't compile
// Swift 3.0: Warning with message
// "Result of call to 'makeViewsVisible()' is unused"
let animationsB = { () -> Void in
self.makeViewsVisible()
}
// Works!
let animationsC = { () -> Bool in
self.makeViewsVisible()
// This is equivalent to writing
// `return self.makeViewsVisible()`
}
}
Fix by either adding @discardableResult
to the method,
@discardableResult func makeViewsVisible() -> Bool {
}
or
let animationsB = { () -> Void in
let _ = self.makeViewsVisible()
}
4. Closures that take no parameters and return Void
You COULD write: () -> ()
OR () -> Void
// Valid!
let closure = { () -> () in
}
// Valid!
let closure = { () -> Void in
}
BUT NOT Void -> ()
// ERROR! Invalid!
let invalidClosure = { /* ERROR! */ Void -> () in
}
But, the easiest is probably:
// Valid!
let closure = {
// Your code
}