Have you read my previous post about beginner tips for Swift developers? Then, let’s get some serious shit out of Swift in this post. I’ll try to cover new features of Swift like keywords, attributes, and operators here.
1. Guard Statement(guard): It is a control statement introduced with v2.0. It takes a boolean value to perform execution ahead. This statement is used for early exit from any function if conditions don’t come up as your expectation. In a certain way it will guard your control flow.
func registerUser(info: [String: String]) {
guard let name = info[“name”],
let email = info[“email”],
let password = info[“password”]
where password.characters.count > 6 else {
// make early exit with proper display message, because user didn’t provide sufficient data for registration.
return
}
// name, email and password would be accessible here knowing they are strings which meets your requirement.
}
2. Defer Statement (defer): How many times in your functions you required to cleanup operations before it returns. Don’t hassle, because swift 2.0 gives you new statement called ‘defer’ which makes sure the number of code you write inside it will be executed only when execution leave the current scope.
func resizeImage(url: NSURL) -> UIImage? {
// ...
let dataSize: Int = ...
let destData = UnsafeMutablePointer.alloc(dataSize)
defer {
destData.dealloc(dataSize)
}
// ...
// All defer block will be called at the end of execution
}
Note that if you have more than one defer blocks in a function. All defer blocks will be called in descending order.
func myfunction() {
// ..
defer {
// block 1
}
// ..
defer {
// block 2
}
defer {
// block 3
}
// ..
// The order of defer block executions will be 3, 2 and 1.
}
As the defer block will be called at the end of current execution; it can handle logical operation.
And, if you’ve an incremental variable which needs to be incremented at the end; you can write it down in defer block.
defer { x += 1 }
3. Autoclosures (@autoclosure): Autoclosures is a syntax closure. You can write it inside your methods to prevent multiple copy of your code. You just write a chunk of code inside two braces, cast it to variable and use it later on where you need that code to be executed multiple times within the method. The code inside of autoclosures do not run until you call the closure.
func myfunction() {
// ..
let hm = {
// body of closure
}
if condition1 {
// ..
if condition2 {
hm()
}
}else {
hm()
}
}
AutoClosures do not take any arguments when it called and it returns the value of the expression wrapped inside it. You can use @autoclosure attribute to mark closure parameter of any function as an autoclosure.
func myfunctionwithclosure(@autoclosure closure: ()->()) {
closure()
}
// calling above function
myfunctionwithclosure(
// body of closure
// note that you don’t need to write curly brace on this closure.
)
4. Nonescaping Closures (@noescape): @noescape is an attribute which tells function that this closure can’t be escaped from here, the scope of the closure is limited within function’s scope.
func myfunctionWithClouser(@noescape closure: ()->()) {
closure()
// This closure can’t escape from here. So you can not assign it to variable
defined out side of this function.
}
It’s good practice to share more information to compiler related to your application logic. Nonescaping closures lets the compiler make more aggressive optimizations because it knows more information about the closure’s lifespan.
Now, when we learned about both Nonescaping closures and Autoclosures. Note that every Autoclosures are Nonescaping. if you want to make any autoclosure escapable, use @autoclosure(escaping) attribute.
5. Nil Coalescing Operator (??): The nil coalescing operator (a ?? b) unwraps an optional ‘a’ if it contains a value, or returns a default value ‘b’ if a is nil.
a != nil ? a! : b
It can be simply used with nil coalescing operator,
a ?? b
where a should be an option value, and b should be of same type as a if a is non-nil, it will be unwrapped.
Example:
let defaultColorName = "red"
var userDefinedColorName: String? // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red”
6. Preventing Overrides (final): You can prevent a method, property or subscript from being overrides by marking it as final. Final is a modifier. Write it before method, property or subscript.
e.g final var, final func, final class func and final subscript
Any attempt to override a final method, property or subscript in subclass is reported as compile-time error. This can be used in class declaration. You can mark any class as final (final class) and the compiler won’t allow that class to override.
7. Dynamic Type Expression (.dynamicType): A dynamicType expression consist of an expression, immediately followed by .dynamicType. It has the following form.
[expression].dynamicType
The expression can’t be the name of a Type. The entire dynamicType expression evaluates to the value of the runtime type of the expression, as the following example shows:
class SomeBaseClass {
class func printClassName() {
print(“SOmeBaseClass”)
}
}
class SomeSubClass: SomeBaseClass {
override class func printClassName() {
print(“SomeSubClass”)
}
}
let someInstance: SomeBaseClass = SomeSubClass()
// someInstance has a static type of SomeBaseClass at compile time, and It has a dynamic type of SomeSubClass at runtime
someInstance.dynamicType.printClassName
8. Dynamic: This is a declaration modifier. Declaration modifiers are keywords or context – sensitive keywords that modify the behaviour or the meaning of a declaration. Apply ‘dynamic’ modifier to any member of a class that can be represented by Objective-C. When you mark a member declaration with dynamic modifier, access to that member is always dynamically dispatched using the Objective-C runtime. Access to that member is never inlined by the compiler.
Because declaration with the dynamic modifier are dispatched using the Objective-C runtime, they are implicitly marked the objc attributes.
There are some other declaration modifiers too in swift like lazy, optional, required and weak. You can learn it from Apple’s swift document.
9. Type Alias Declaration (typealias): A type alias declaration introduces a named alias of an existing type into your program. It is more like ‘typedef’ of Objective-C and C. Type alias declaration are declared using the ‘typealias’ keyword and have the following form.
typealias [name] = [existing type]
for example:
typealias WSBlock = (json: AnyObject?, flag: Int) -> ()
typealias MyInt = Int
After declaring a type alias, the aliased name cab can be used instead of the existing type everywhere in your program. The existing type can be a named type or a compound type. Type aliases do not create new types, they simply allow a name to refer to an existing type.
10. Access levels (Public, Internal & Private): Swift provides three different access levels for the entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.
– ‘Public’ access enables entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use public access when specifying the public interface to a framework.
– ‘Internal’ access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure.
– ‘Private’ access restricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality.
Public access is the highest (least restrictive) access level and private access are the lowest (or most restrictive) access level.