Created
October 7, 2015 07:47
-
-
Save hamvocke/8d033cce2db9bf23cd6d to your computer and use it in GitHub Desktop.
Swift 2.0: What's new, what's better -- interactive playground for the talk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Playground - noun: a place where people can play | |
import XCPlayground | |
import Foundation | |
import UIKit | |
struct UserProfile { | |
var username: String | |
var confirmed: Bool | |
} | |
//: # Error Handling | |
//: Defining Error Types | |
enum UserPermissionError: ErrorType { | |
case WrongPassword | |
case UserBanned(until: Int) | |
case Unconfirmed | |
} | |
//: Throwing Errors | |
func loadUserProfile() throws -> UserProfile { | |
throw UserPermissionError.WrongPassword | |
} | |
//: Basic Error Handling | |
do { | |
try loadUserProfile() | |
} catch UserPermissionError.WrongPassword { | |
print("Ooops, that has gone horribly wrong") | |
} | |
//: with Optional Values | |
let profile = try? loadUserProfile() | |
//: # Optional Checking | |
//: Old-fashioned way | |
func optionals(x: Int?) { | |
if x == nil || x <= 0 { | |
return | |
} | |
x!.description | |
} | |
optionals(nil) | |
optionals(0) | |
optionals(3) | |
//: Swift 1.2 style | |
func optionalsWithIfLet(x: Int?) { | |
if let x = x where x > 0 { | |
x.description | |
} | |
} | |
optionalsWithIfLet(nil) | |
optionalsWithIfLet(0) | |
optionalsWithIfLet(4) | |
//: Swift 2.0 style -- Guards to the rescue | |
func optionalsWithGuard(x: Int?) { | |
guard let x = x where x > 0 else { | |
return | |
} | |
x.description | |
} | |
optionalsWithGuard(nil) | |
optionalsWithGuard(0) | |
optionalsWithGuard(4) | |
//: Avoiding the pyramid of doom | |
//var customer = ["user": ["address" : ["country": "DE"]]] | |
//func parseJson(customer: [String:AnyObject]) { | |
// guard let user = customer["user"] else { | |
// return | |
// } | |
// | |
// guard let address = user["address"]! else { | |
// return | |
// } | |
// | |
// guard let country = address["country"]! else { | |
// return | |
// } | |
// | |
// print(country) //"DE" | |
//} | |
//: Simple Guard statement | |
func loadUserProfile(username: String?) -> UserProfile? { | |
guard let name = username where name == "Jan" else { | |
return nil | |
} | |
return UserProfile(username: "Jan", confirmed: true) | |
} | |
loadUserProfile("Ham") | |
loadUserProfile("Jan") | |
//: With Exceptions | |
//func loadUserProfile(username: String?) -> UserProfile { | |
// guard let name = username where name == "Jan" else { | |
// throw UserPermissionError.UserBanned(until: 1443778627) | |
// } | |
// | |
// return UserProfile(username: "Jan", confirmed: true) | |
//} | |
// | |
//do { | |
// try loadUserProfile("Ham") | |
//} catch let UserPermissionError.UserBanned(bannedUntil) { | |
// print("User is Banned until \(bannedUntil)") | |
//} | |
// | |
//let jan = try? loadUserProfile("Jan") | |
//:# Defer | |
func loadProfilePic() { | |
print("Opening File Handle") | |
defer { print("Close File Handle") } | |
print("Process File") | |
} | |
func loadAllFiles() { | |
print("Loading all needed files") | |
loadProfilePic() | |
print("All files loaded") | |
} | |
loadAllFiles() | |
//: # Protocol Extensions | |
//: A cross cutting concern. We want to use loggers everywhere | |
protocol Logger { | |
func log(message:String) | |
} | |
//: A basic blueprint of our "Account" domain model | |
protocol Account { | |
var firstName: String { get } | |
var lastName: String { get } | |
func fullName() -> String | |
} | |
//: Our first protocol extension | |
extension Logger { | |
func log(message:String) { | |
print ("log msg: \(self.dynamicType): \(message)") | |
} | |
} | |
//: Our first implementation of the extended protocol | |
struct Tweet: Logger { | |
var date: Int | |
var author: String | |
var text: String | |
func getText() -> String { | |
log("Having fun!") | |
log | |
return "@\(author): \(text) (send at \(date)" | |
} | |
} | |
let tweet = Tweet(date: 1443778627, author: "hamvocke", text: "Yo! Check out @thilo's amazing talk about protocol-oriented programming!") | |
tweet.getText() | |
//: Declaring conditions on the type for a type specific extension | |
extension Logger where Self: Account { | |
func log(message:String) -> (){ | |
print ("nice log msg: \(NSDate()) \(self.dynamicType): \(message)") | |
} | |
} | |
//: A first struct which acts as a concrete implementation of our Account | |
struct UserAccount: Account, Logger { | |
var firstName: String | |
var lastName: String | |
func fullName() -> String { | |
log("printing my full name") //prettyLog is available here! | |
return "\(firstName) \(lastName)" | |
} | |
} | |
let account = UserAccount(firstName: "Ham", lastName: "Vocke") | |
account.fullName() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment