- 10 tips to become a better developer
- Top Developer Mistakes
- Introduction to Protocol-Oriented Programming
- Simple, Effective and Robust Network model for iOS applications using Protocol Oriented Programming
- A different way to deal with localized strings
- Half-Baked Solutions for Common RxSwift Problems
- Writing High-Performance Code
- Avoiding Primitive Obsession
- A Complete Guide to Network Unit Testing
Properties
var red, gree, blue: Double // create 3 variables of type Double
print("Some text", terminator: "") // doen't jump a line, because terminator by default is \n
Optionals
if let firstNumber = Int("4"), secondNumber = Int("42") where firstNumber > secondNumber {
// this line is NOT executed
}
Int
Use
UInt
when you especifically need an unsigned integer type with the same size as the platform's native word size.
Swift provides a type Int
which has the same size as the current platform's native word size. On a 32-bit platform, Int
is the same size as Int32
and on a 64-bit platform, Int
is the same size as Int64
.
Double
Double
has a precision of at least 15 decimal digits, whereas the precision ofFloat
can be as little as 6 decimal digits;- In situation where either type would be appropriate,
Double
is preferred; - Swift always chooses
Double
when inferring floating point numbers.
Numeric Literals
let decimal = 17
let binary = 0b10001 // 17
let octal = 0o21 // 17 as well
let hexadecimal = 0x11 // 17 again
let floatingPoint = 1.25e2 // 1.25 x 10²
let floatingHexa = 0xFp2 // means 15 x 2²
let bigNumber = 1_000_000 // the underscores are ignored
Type Alias
Once you define a type alias, you can use the alias anywhere you might use the original name:
typealias AudioSample = UInt16
var maxAmplitude = AudioSample.min
Tuples
let http404Error = (404, "Not Found")
let (statuCode, statusMessage) // let statusCode = 404; let statusMessage == "Not Found"
Named elements:
let http200Status = (statusCode: 200, description: "Ok")
print(http200Status.statusCode) // prints 200
class SomeManager {
static let sharedInstance = SomeManager()
}
Usage:
let sharedInstance = SomeManager.sharedInstance
Lazy initialization with closure:
lazy var test: String = {
[unowned self] in
return "another's variable value is \(self.anotherVariable)"
}
Lazy initialization with a method:
lazy var players: [String] = self.initialPlayers()
func initialPlayers() -> [String] {
var players = ["John Doe"]
return players
}
Improve readability of constants using nested structs:
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
}
}
let url = Constants.FoursquareApi.BaseUrl
User defer
to place code that will be execute whenever a function is leaving scope:
func deferExample() {
defer {
print("Leaving scope, time to cleanup!")
}
print("Performing some operation...")
}
import Foundation
/**
Executes the closure on the main queue after a set amount of seconds.
- parameter delay: Delay in seconds
- parameter closure: Code to execute after delay
*/
func delayOnMainQueue(delay: Double, closure: ()->()) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), closure)
}
/**
Executes the closure on a background queue after a set amount of seconds.
- parameter delay: Delay in seconds
- parameter closure: Code to execute after delay
*/
func delayOnBackgroundQueue(delay: Double, closure: ()->()) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), closure)
}
- map applies a closure to each value in the collection then returns an array of the map result type filled with the mapped values;
- filter applies a function to each value in our array and returns a Bool value. Values that return true are returned in the resulting array while values that returned false are not;
- In reduce the first argument is the first reduced value ( 0 in the case below). Its second argument is a function that has access to the previously reduced value and the current value of the array. In this example, our function is + which simply adds the previous value of the function to the current item in the array.
let ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let strings = ints.map { return String($0) } // returns ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let evenInts = ints.filter { return ($0 % 2 == 0) } // returns [0, 2, 4, 6, 8]
let reducedInts = ints.reduce(0, combine: +) // returns 45
// defined another way:
let reducedIntsAlt = ints.reduce(0) { (previousValue: Int, currentValue: Int) -> Int in
return previousValue + currentValue // returns 45
}
let optionalName: String? = nil
let nameCount = optionalName?.characters.count ?? 0 // returns 0
protocol Shakable {
}
extension Shakable where Self: UIView {
func shake() {
print("I'm shaking!")
}
}
class MyButton: UIView, Shakable {
func callShakeMethod() {
shake() // Works
}
}
class AnotherClass: NSObject, Shakable {
func callShakeMethod() {
shake() // error!
}
}