Top Banner
Idioms in Swift Kaz Yoshikawa May 2016
51

Idioms in swift 2016 05c

Apr 12, 2017

Download

Engineering

Kaz Yoshikawa
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Idioms in swift 2016 05c

Idioms in SwiftKaz Yoshikawa

May 2016

Page 2: Idioms in swift 2016 05c

About me

Page 3: Idioms in swift 2016 05c

Kaz Yoshikawa• Electricwoods LLC 代表 / Digital Lynx Systems Inc. 副代表

• e-mail: [email protected]

• LinkedIn: https://www.linkedin.com/in/kazyoshikawa

• Working History

• Adobe Systems (Tokyo)

• Lionbridge (Tokyo)

• Quark (Tokyo / Denver)

• Hummingbird Communications (Mt. View, USA)

• Fact International (Vancouver, Canada)

• Perle Systems (Toronto, Canada), etc.

Page 4: Idioms in swift 2016 05c

Engineering

Page 5: Idioms in swift 2016 05c

将棋盤Kit

Page 6: Idioms in swift 2016 05c

What is Idiom?

Page 7: Idioms in swift 2016 05c

Optional

Page 8: Idioms in swift 2016 05c

guard let• 二つの引数が nil でない事を保証する

func add(a: Int?, _ b: Int?) -> Int? {

guard let a = a, let b = b else { return nil }

return a + b }

Page 9: Idioms in swift 2016 05c

if let• if let を使う

func add(a: Int?, _ b: Int?) -> Int? {

if let a = a, let b = b { return a + b } return nil

}

Page 10: Idioms in swift 2016 05c

where• guard let で0以上を保証する

func add(a: Int?, _ b: Int?) -> Int? { guard let a = a, let b = b where a >= 0 && b >= 0 else { return nil } return a + b }

• if let でも0以上を保証する func add(a: Int?, _ b: Int?) -> Int? { if let a = a, let b = b where a >= 0 && b >= 0 { return a + b } return nil }

Page 11: Idioms in swift 2016 05c

nil-coalescing Operator• nil の場合は 0 として扱う func add(a: Int?, b: Int?) -> Int {

return (a ?? 0) + (b ?? 0)

}

Page 12: Idioms in swift 2016 05c

Switch

Page 13: Idioms in swift 2016 05c

Optional in Switch• 実は optional も switch 文に使える

func countryName(identifier: String?) -> String? { switch identifier { case "JP"?: return "Japan" case "GB"?: return "England" case "US"?: return "U.S.A." default: return nil } }

Page 14: Idioms in swift 2016 05c

Late InitializingImmutable Variables

• 初期値を後で設定する不定変数

let color: UIColor // "= value"

switch value % 3 { case 0: color = UIColor.whiteColor() case 1: color = UIColor.redColor() default: fatalError() }

• 初期化しないケースがあると、コンパイルエラー

Page 15: Idioms in swift 2016 05c

Complex switch casesfor thing in things { switch thing { case 0 as Int: print("zero as an Int") case 0 as Double: print("zero as a Double") case let someInt as Int: print("an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: print("a positive double value of \(someDouble)") case is Double: print("some other double value") case let someString as String: print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("an (x, y) point at \(x), \(y)") case let movie as Movie: print("Movie:'\(movie.name)'") default: print("something else") } }

Page 16: Idioms in swift 2016 05c

Implicitly Unwrapped Optional

Page 17: Idioms in swift 2016 05c

Implicitly Unwrapped Optional with if statement

• Implicitly Unwrapped Optional でも if let は 使える

let a: Int! if let a = a { print("\(a)") }

Page 18: Idioms in swift 2016 05c

Implicitly Unwrapped Optional with guard statement

• Implicitly Unwrapped Optional でも guard は 使える

class MyObject { var value: Int! = nil func some() { guard let value = value else { return } print("\(value)") } func other() { guard value != nil else { return } print("\(value)") } }

Page 19: Idioms in swift 2016 05c

Associated Values

Page 20: Idioms in swift 2016 05c

Defining Associated Value

enum Element { case String(Swift.String) case Boolean(Bool) case Integer(Int) case Float(Swift.Float) case Dictionary([Swift.String: Element]) case Array([Element]) case Null }

let integer = Element.Integer(42) let city = Element.String("Tokyo") let cities = Element.Array([city]) let dictionary = Element.Dictionary(["items": array])

Page 21: Idioms in swift 2016 05c

Extracting Associated Values Using switch Statement

• Associated Value を Switch文で取り出す

switch element { case .String(let string): print("string: \(string)") case .Boolean(let value): print("boolean: \(value)") case .Integer(let value): print("ineteger: \(value)") case .Float(let value): print("float: \(value)") case .Dictionary(let dictionary): print("dictionary: \(dictionary)") case .Array(let array): print("array: \(array)") case .Null: print("null") }

Page 22: Idioms in swift 2016 05c

Extracting Associated Values using if Statement

• If 文でも取り出せます

let element1: Element = … if case .String(let string) = element1 { print("\(string)") }

• Optional な場合でも取り出せます

let element: Element? = … if case .String(let string)? = element1 { print("\(string)") }

Page 23: Idioms in swift 2016 05c

Extracting Associated Values

• division -> members -> person -> name

let name = Element.String("John") let john = Element.Dictionary(["name": name]) let members = Element.Array([john]) let group = Element.Dictionary(["members": members])

• 一発で取り出せる

if case .Dictionary(let group) = group, case .Array(let members)? = division["members"], case .Dictionary(let member)? = members.first, case .String(let name)? = member["name"] { print("\(name)") // John }

Page 24: Idioms in swift 2016 05c

Closure

Page 25: Idioms in swift 2016 05c

Basic Closureclass MyViewController: UIViewController { var state: Bool = false func toggle(animated: Bool) { let closure = { self.view.backgroundColor = self.state ? UIColor.redColor() : UIColor.whiteColor() self.state = !self.state } if animated { UIView.animateWithDuration(0.3) { closure() // <-- Here!! } } else { closure() // <-- Here!! } } }

Page 26: Idioms in swift 2016 05c

Basic Closureclass MyViewController: UIViewController { var state: Bool = false func toggle(animated: Bool) { let closure = { self.view.backgroundColor = self.state ? UIColor.redColor() : UIColor.whiteColor() self.state = !self.state } if animated { UIView.animateWithDuration(0.3) { closure() // <-- Here!! } } else { closure() // <-- Here!! } } }

Page 27: Idioms in swift 2016 05c

Execute on Main Thread func dispatch_sync_main(block: () -> Void) { if NSThread.isMainThread() { block() } else { dispatch_sync(dispatch_get_main_queue()) { () -> Void in block() } } }

dispatch_sync_main { self.tableView.reloadData() }

Page 28: Idioms in swift 2016 05c

Execute on Main Thread func dispatch_sync_main(block: () -> Void) { if NSThread.isMainThread() { block() } else { dispatch_sync(dispatch_get_main_queue()) { () -> Void in block() } } }

dispatch_sync_main { self.tableView.reloadData() }

Page 29: Idioms in swift 2016 05c

Execute on Main Thread func dispatch_sync_main(block: () -> Void) { if NSThread.isMainThread() { block() } else { dispatch_sync(dispatch_get_main_queue()) { () -> Void in block() } } }

dispatch_sync_main { self.tableView.reloadData() }

Page 30: Idioms in swift 2016 05c

Initialize Immutable Variable Using Closure

• closure と switch 文を使うとかっこよく書ける let color: UIColor = { switch value % 2 { case 0: return UIColor.whiteColor() case 1: return UIColor.redColor() default: fatalError() } }() // "()" !!

Page 31: Idioms in swift 2016 05c

Initialize Immutable Variable Using Closure

• closure と switch 文を使うとかっこよく書ける let color: UIColor = { switch value % 2 { case 0: return UIColor.whiteColor() case 1: return UIColor.redColor() default: fatalError() } }() // "()" !!

Page 32: Idioms in swift 2016 05c

Changing Behavior with Using Closure

typealias DrawingHandler = (UIPanGestureRecognizer)->()

class MyView: UIView { func panGesture(sender: UIPanGestureRecognizer) { self.drawingHandler(sender) } var drawingHandler: DrawingHandler! let ovalGesture: DrawingHandler = { gesture in // draw oval } let rectangleGesture: DrawingHandler = { gesture in // draw rectangle } }

Page 33: Idioms in swift 2016 05c

Changing Behavior with Using Closure

typealias DrawingHandler = (UIPanGestureRecognizer)->()

class MyView: UIView { func panGesture(sender: UIPanGestureRecognizer) { self.drawingHandler(sender) } var drawingHandler: DrawingHandler! let ovalGesture: DrawingHandler = { gesture in // draw oval } let rectangleGesture: DrawingHandler = { gesture in // draw rectangle } }

Page 34: Idioms in swift 2016 05c

lazy

Page 35: Idioms in swift 2016 05c

When should I use lazy?• 処理が重くて初期化時に実行するのは不都合

• 大人の理由で init で初期化できないプロパティ

Page 36: Idioms in swift 2016 05c

Using lazy varclass MyObject {

lazy var path: String = { return NSBundle.mainBundle() .pathForResource("text", ofType: "txt")! }()

lazy var text: String = { return try! String(contentsOfFile: self.path) }() }

Page 37: Idioms in swift 2016 05c

Initializing code per instance

• 何回呼ばれてもインスタンス毎に一度のみ初期化するコード

class MyView: UIView {

override func layoutSubviews() { print("MyView: \(#function)") super.layoutSubviews() setup() }

private lazy var setup: (()->()) = { print("MyView: \(#function)") // さまざまな初期化のコード return {} }() }

http://qiita.com/codelynx/items/f0243d631f2448e89026

Page 38: Idioms in swift 2016 05c

Singleton

Page 39: Idioms in swift 2016 05c

Singleton• 典型的なシングルトン class Manager { static let sharedManager = Manager() private init() { } }

• クロージャーを使ったシングルトン

class Manager { static var sharedManager: Manager = { return Manager() }() private init() { } }

http://qiita.com/codelynx/items/a936afe0a45d4cf5abfb

Page 40: Idioms in swift 2016 05c

Updating C style `for` statement

http://qiita.com/codelynx/items/899c26dd2cbdba7d2b00

Page 41: Idioms in swift 2016 05c

for var i = 0 ; i < 100 ; i++// C-Style for statement for var i = 0 ; i < 100 ; i++ { print("\(i)") }

// Swift 3.0 ready (0 ..< 100).forEach { print("\($0)") }

// Swift 3.0 ready for i in (0 ..< 100) { print("\(i)") }

Page 42: Idioms in swift 2016 05c

for var i = 99 ; i >= 0 ; i--// C-Style for statement for var i = 99 ; i >= 0 ; i-- { print("\(i)") }

// Swift 3.0 ready (0 ..< 100).reverse().forEach { print("\($0)") }

// Swift 3.0 ready for i in (0 ..< 100).reverse() { print("\(i)") }

Page 43: Idioms in swift 2016 05c

for var i = 0; i < 100 ; i += 2// C-Style for statement for var i = 0; i < 100 ; i += 2 { print("\(i)") }

// Swift 3.0 ready 0.stride(to: 100, by: 2).forEach { print("\($0)") }

Page 44: Idioms in swift 2016 05c

for var i = 98 ; i >= 0 ; i -= 2

// C-Style for statement for var i = 98 ; i >= 0 ; i -= 2 { print("\(i)") }

// Swift 3.0 ready 98.stride(through: 0, by: -2).forEach { print("\($0)") }

// Swift 3.0 ready

0.stride(to: 100, by: 2).reverse().forEach { print("\($0)") }

// Swift 3.0 ready for i in 0.stride(to: 100, by: 2).reverse() { print("\(i)") }

Page 45: Idioms in swift 2016 05c

for without increment• 次の再初期化式の指定がなく、刻みが不定の場合 // C-Style for statement for var i = 0 ; i < 100 ; { print("\(i)") if (i * i) % 2 == 0 { i += 1 } else { i += 2 } }

// Swift 3.0 ready var i = 0 while i < 100 { print("\(i)") if (i * i) % 2 == 0 { i += 1 } else { i += 2 } }

Page 46: Idioms in swift 2016 05c

Computed Properties and Property Observer

Page 47: Idioms in swift 2016 05c

Custom Propertyclass MyObject {

private var _name: String = ""

var name: String { get { return _name } set { _name = newValue } }

}

Page 48: Idioms in swift 2016 05c

Property Observerclass MyView: UIView {

var name: String = "" { didSet { self.setNeedsLayout() } }

}

Page 49: Idioms in swift 2016 05c

Wrap Up

Page 50: Idioms in swift 2016 05c

Wrap up• 知っていても、0.2秒で思い出せない記法はいろいろある

• Open Source を散策して先人達の記法を参考に

• 気がついた記法があれば、playground などにメモ

• 時々、swift 文法書を眺め直してみよう

Page 51: Idioms in swift 2016 05c

Thank YouKaz Yoshikawa

[email protected]