Why You should use Swift
Type safe
Don’t need to check hundred times, don’t need NSParameterAssert in most cases.
if (username.length > 0) {
[[MWEDaemon daemon].currentInterfaceController didReceivedYoCount:count fromUsername:username type:type];
}func didReceivedYoCount(count: UInt, fromUsername username: String, type: Int) {
presentControllerWithName("MWEYoController", context: ["username": username, "count": count, "type": type])
}- (void)didReceivedYoCount:(NSUInteger)count fromUsername:(NSString *)username type:(int)type {
// already check nil parameters when call
if (username == nil) {
return;
}
NSParameterAssert(username);
[self presentControllerWithName:@"MWEYoController" context:@{@"username": username, @"count": @(count), @"type": @(type)}];
}Generics
struct IntStack {
var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
}struct Stack<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}Enum
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
switch productBarcode {
case let .UPCA(numberSystem, manufacturer, product, check):
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .QRCode(productCode):
print("QR code: \(productCode).")
}
// prints "QR code: ABCDEFGHIJKLMNOP."There is another a very popular use case about check result, here is a example in Alamofire/Result.swift
Default Prameter Values
Function definition will be much more graceful.
func someFunction(parameterWithDefault: Int = 22) {
// function body goes here
}
// call
someFunction()
someFunction(1)Functions with Multiple Return Values (Tuples)
func minMax(array: [Int]) -> (min: Int, max: Int)? {
// function body goes here
}Function Types as Parameter Types
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)Closure Expressions
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]All of the codes below do the same thing:
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sort(backwards)reversed = names.sort({ (s1: String, s2: String) -> Bool in
return s1 > s2
})reversed = names.sort({ s1, s2 in return s1 > s2 })reversed = names.sort({ s1, s2 in s1 > s2 })reversed = names.sort({ $0 > $1 })reversed = names.sort(>)guard
Before:
func somethingDidChanged(notification: NSNotification) {
if let contact = notification.userInfo?["contact"] as? MWEContact {
if let message = notification.userInfo?["message"] as? MWEMessage {
// do something
}
}
}
After:
func somethingDidChanged(notification: NSNotification) {
guard let contact = notification.userInfo?["contact"] as? MWEContact else {
return
}
guard let message = notification.userInfo?["contact"] as? MWEMessage else {
return
}
// do something
}Could be better:
func somethingDidChanged(notification: NSNotification) {
guard let contact = notification.userInfo?["contact"] as? MWEContact,
message = notification.userInfo?["message"] as? MWEMessage else {
return
}
// do something
}defer
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer {
close(file)
}
while let line = try file.readline() {
// Work with the file.
}
// close(file) is called here, at the end of the scope.
}
}Protocol Extensions
- WWDC 2015 - Session 408 - Protocol-Oriented Programming in Swift
class PresentErrorViewController: UIViewController {
var errorViewIsShowing: Bool = false
func presentError(message: String = “Error!", withArrow shouldShowArrow: Bool = false, backgroundColor: UIColor = ColorSalmon, withSize size: CGSize = CGSizeZero, canDismissByTappingAnywhere canDismiss: Bool = true) {
//do complicated, fragile logic
}
}
//Over 100 classes inherited from this class, by the way.
class EveryViewControllerInApp: PresentErrorViewController {}protocol ErrorPopoverRenderer {
func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool)
}
extension UIViewController: ErrorPopoverRenderer { //Make all the UIViewControllers that conform to ErrorPopoverRenderer have a default implementation of presentError
func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool) {
//add default implementation of present error view
}
}
class KrakenViewController: UIViewController, ErrorPopoverRenderer { //Drop the God class and make KrakenViewController conform to the new ErrorPopoverRenderer Protocol.
func methodThatHasAnError() {
//…
//Throw error because the Kraken sucks at eating Humans today.
presentError(/*blah blah blah much parameters*/)
}
}the Swift runtime calls the presentError() through static dispatch instead of through dynamic dispatch.
Some code snippets
let b = a ?? "default"if #available(iOS 9, OSX 10.10, *) {
// Use iOS9 APIs on iOS, and use OS X v10.10 APIs on OS X
} else {
// Fall back to earlier iOS and OS X APIs
}prepareSomething() // NOT use 'self.' unless it's necessary
// self.prepareSomething() // don't do this
contact.getHeadImageThumbnail { [weak self] (object, error) -> Void in
// blabla
self.updateUI()
}Tips
Use Playground to test something when coding.

Summay
