Friday 6 May 2016

Swift Tips You May Not Know But Should

Improve the Readability of Constants
A neat way to utilize structs in Swift is to make a file for all the constants in our application. This is useful because Swift allows us to nest structures like so:
import Foundation

struct Constants {

    struct FoursquareApi {
        static let BaseUrl = "https://api.foursquare.com/v2/"
    }
    
    struct TwitterApi {
        static let BaseUrl = "https://api.twitter.com/1.1/"
    }

    struct Configuration {
        static let UseWorkaround = true
    }
    
}
This nesting gives us a namespace for our constants. For example, we could useConstants.FoursquareApi.BaseUrl to access Foursquare's BaseUrl constant. This makes things more readable and provides a layer of encapsulation around related constants.
Avoid NSObject and @objc to Improve Performance
Swift allows us to extend classes from NSObject to get Objective-C runtime features for an object. It also allows us to annotate Swift methods with @objc to allow the methods to be used by the Objective-C runtime.
Supporting the Objective-C runtime means that method calls are going to be using dynamic dispatch instead of static or vtable dispatch. This end result is that methods that support the Objective-C runtime have a four times performance penalty when called. In practical usage, the performance hit may be negligible but the cool thing is that armed with this knowledge, we now know that method execution in Swift is four times faster than Objective-C.
Use Method Swizzling in Swift
Method swizzling is a technique that substitutes one method implementation for another. If you're not familiar with swizzling, check out this blog post. Swift optimizes code to call direct memory addresses instead of looking up the method location at runtime as in Objective-C. So by default swizzling doesn’t work in Swift classes unless we:
  • Disable this optimization with the dynamic keyword. This is the preferred choice, and the choice that makes the most sense if the codebase is entirely in Swift.
  • Extend NSObject. Never do this only for method swizzling (use dynamicinstead). It’s useful to know that method swizzling will work in already existing classes that have NSObject as their base class, but we're better off selectively choosing methods with dynamic .
  • Use the @objc annotation on the method being swizzled. This is appropriate if the method we would like to swizzle also needs to be exposed to Objective-C code at the same time.
Update: As requested, we've added an example of swizzling purely in Swift. It still requires the Objective-C runtime, but our class doesn’t inherit from NSObject and our methods are not marked as @objcClick here to see it in action in a playground.
import UIKit
​
class AwesomeClass {
    dynamic func originalFunction() -> String {
        return "originalFunction"
    }
    
    dynamic func swizzledFunction() -> String {
        return "swizzledFunction"
    }
}
​
let awesomeObject = AwesomeClass()
​
print(awesomeObject.originalFunction()) // prints: "originalFunction"
​
let aClass = AwesomeClass.self
let originalMethod = class_getInstanceMethod(aClass, "originalFunction")
let swizzledMethod = class_getInstanceMethod(aClass, "swizzledFunction")
method_exchangeImplementations(originalMethod, swizzledMethod)
​
print(awesomeObject.originalFunction())  // prints: "swizzledFunction"
Reference: http://savvyapps.com/blog/swift-tips-for-developers

No comments:

Post a Comment