Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

What's New in Swift 4

384 views

Published on

Let'Swift 2017년 9월 23일

Published in: Software
  • Be the first to comment

What's New in Swift 4

  1. 1. letswift(17) What’s New in Swift 4 Fancy김영후
  2. 2. letswift(17) What’s New in Swift 4
  3. 3. letswift(17) What’s New in Swift 3 ?
  4. 4. letswift(17) What’s New in Swift 2 ?
  5. 5. letswift(17) What’s New in Swift 1.2 ?
  6. 6. Swift 1.2 if let data = dataStream.data { if let encoding = data.encoding { //Swift 1.0 } } if let data = dataStream.data, let encoding = data.encoding where somethingTrue { //Swift 2.0 } }
  7. 7. Swift 2 guard let frog = frog, let cow = cow else { return } extension MyViewController: UITableViewDataSource { //implement UITableViewDataSource }
  8. 8. Swift 2 enum DrinkError: ErrorType { case NoBeerRemainingError } func drinkWithError() throws { if beer.isAvailable() { } else { throw DrinkError.NoBeerRemainingError } } do { try drinkWithError() } catch { print(error) }
  9. 9. Swift 3 helloString.stringByAppendingString("world") helloString.appending("world") UIColor.blueColor().colorWithAlphaComponent(0.5) UIColor.blue.withAlphaComponent(0.5) NSBundle.mainBundle() Bundle.main numbers.maxElement() numbers.max() animals.insert("Koala", atIndex: 0) animals.insert("Koala", at: 0) WKInterfaceDevice.currentDevice() WKInterfaceDevice.current() device.playHaptic(.success) device.play(.success)
  10. 10. Swift 3 UIStatusBarStyle.LightContent UIStatusBarStyle.lightContent SKLabelVerticalAlignmentMode.Center SKLabelVerticalAlignmentMode.center Optional<String>.None Optional<String>.none
  11. 11. letswift(17) What’s New in Swift 4
  12. 12. letswift(17) Multi-Line String Literals
  13. 13. Multi-Line Literals let message = """ 이것은 멀티라인 문자열 “"" //let single = """이것은 불가능"""
  14. 14. Multi-Line Literals let single2 = """ 이것은 싱글라인 """
  15. 15. Multi-Line Literals let indentation = """ 1 2 3 """ // 1n 2n 3
 
 
 let indentation = """ 1 2 3 """ //1n2n3
  16. 16. Multi-Line Literals let indentation = """ 1 2 3 “"" //Error: change indentation of this line to match closing delimiter let indentation = """ 1 2 3 """
  17. 17. letswift(17) String
  18. 18. Collections once again let string = "abcdefg" print(string.characters.count) print(string.count) let cow = "Cow 🐮" for char in cow { print(char) } cow.count // 5 cow.isEmpty // false cow.dropFirst() // "ow 🐮" String(cow.reversed()) // "🐮 owC”
  19. 19. Unicode 9 """.count // Now: 1, Before: 2 "#".count // Now: 1, Before: 2 "$".count // Now: 1, Before, 4
  20. 20. Substring, StringProtocol protocol StringProtocol : BidirectionalCollection { // Implementation detail as described above } extension String : StringProtocol, RangeReplaceableCollection { typealias SubSequence = Substring subscript(bounds: Range<String.Index>) -> Substring { ... } } struct Substring : StringProtocol, RangeReplaceableCollection { typealias SubSequence = Substring // near-identical API surface area to String }
  21. 21. Substring, StringProtocol let endIndex = cow.index(cow.startIndex, offsetBy: 2) var cowSubstring = cow[cow.startIndex...endIndex] type(of: cowSubstring) // Substring.Type // Concatenate a String onto a Substring cowSubstring += "🥛" // "Milk🥛" // Create a String from a Substring let milkString = String(cowSubstring) // "Milk🥛"
  22. 22. letswift(17) Private
  23. 23. private, fileprivate class Person { private let name: String init(name: String, age: Int) { self.name = name } } extension Person: CustomStringConvertible { var description: String { //Swift 3에선 fileprivate로 해야 컴파일 가능 return "(self.name)" } }
  24. 24. fileprivate in Swift 3 Extension Oriented Programming을 밀면서 fileprivate이 사실상 private 역할을 하게 됨 Swift3 private은 extension에서 접근 하지 못하는 필 드들을 구분할 수 있으나 과연 의미가 있는 구분인가? Swift4 private “같은 소스 파일”에 있는 extension은 private 필드에 접근 가능함
  25. 25. fileprivate in Swift 4.0 class Person { fileprivate var name: String init(name: String) { self.name = name } } func run() { let p = Person(name: "Younghoo") p.name = "0hoo" //fileprivate 필드는 같은 파일에서 접근 가능 }
  26. 26. letswift(17) Smart KeyPaths
  27. 27. KeyPaths struct Person { var name: String } struct Book { var title: String var authors: [Person] var primaryAuthor: Person { return authors.first! } } let abelson = Person(name: "Harold Abelson") let sussman = Person(name: "Gerald Jay Sussman") let book = Book(title: "Structure and Interpretation of Computer Programs", authors: [abelson, sussman])
  28. 28. KeyPaths book[keyPath: Book.title] //"Structure and Interpretation of Computer Programs" book[keyPath: Book.primaryAuthor.name] //"Harold Abelson” let authorKeyPath = Book.primaryAuthor let nameKeyPath = authorKeyPath.appending(path: .name) book[keyPath: nameKeyPath] //"Harold Abelson"
  29. 29. KVO import Foundation class Child: NSObject { let name: String // KVO-enabled properties must be @objc dynamic @objc dynamic var age: Int init(name: String, age: Int) { self.name = name self.age = age super.init() } func celebrateBirthday() { age += 1 } }
  30. 30. KVO, KeyPaths let eugene = Child(name: "Eugene", age: 0) let observation = eugene.observe(.age, options: [.initial, .old]) { (child, change) in if let oldValue = change.oldValue { print("(child.name)’s age changed from (oldValue) to (child.age)") } else { print("(child.name)’s age is now (child.age)") } }
 //Eugene’s age is now 0 eugene.celebrateBirthday() //Eugene’s age changed from 0 to 1
  31. 31. 옛날 옛적에… //Objective-C [self.controller addObserver:self forKeyPath:@"isEnabled" options:NSKeyValueObservingOptionNew context:nil]; [self addObserver:self forKeyPath:@"controller.isEnabled" options:NSKeyValueObservingOptionNew context:nil]; //Swift 2 addObserver(self, forKeyPath: "isEnabled", options: [], context: nil) //Swift 3 addObserver(self, forKeyPath: #keyPath(isEnabled), options: [.old, .new], context: nil)
  32. 32. letswift(17) Existentials
  33. 33. 1. (격식) (인간의) 존재에 관한[관련된] 2. (철학) 실존주의적인
  34. 34. Existentials protocol Saveable { func save() } protocol Loadable { func load() } func doThing(thing: protocol<Saveable, Loadable>) { thing.save() thing.load() }
  35. 35. Swift 3 SE-0095 func doThing(thing: Saveable & Loadable) { thing.save() thing.load() } func secondFunc<T : Saveable & Loadable>(x: T) { }
  36. 36. Class and subtype func reload(view: UIView & Reloadable) { }
  37. 37. letswift(17) One-Sided Ranges
  38. 38. One-Sided Ranges let planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", “Neptune"] let outsideAsteroidBelt = planets[4...] // Before: planets[4..<planets.endIndex] let firstThree = planets[..<4] // Before: planets[planets.startIndex..<4]
  39. 39. Pattern Matching func temperature(planetNumber: Int) { switch planetNumber { case ...2: // anything less than or equal to 2 print("더워") case 4...: // anything greater than or equal to 4 print("추워") default: print("좋아") } } temperature(planetNumber: 3)
  40. 40. letswift(17) Limiting @objc inference
  41. 41. @objc Objective-C에 노출되는 코드는 @objc가 필요 Swift3에서 자동으로 추론함 • 사용자가 @objc를 원하는지 알기 어려움 • 컴파일러가 메타데이터를 생성해야 함 • 6~8%의 바이너리 사이즈 증가
  42. 42. @objc 이제 자동으로 추론되지 않는다 여전히 추론되는 예외 class Super { @objc func foo() { } } class Sub : Super { /* inferred @objc */ override func foo() { } }
  43. 43. @objc @objc protocol MyDelegate { func bar() } class MyClass : MyDelegate { /* inferred @objc */ func bar() { } } @IBAction, @IBOutlet, @NSManaged, @IBInspectable 등
  44. 44. @objc dynamic은 더 이상 자동으로 추론되지 않음 class MyClass { dynamic func foo() { } // error: 'dynamic' method must be '@objc' @objc dynamic func bar() { } // okay } ??? dynamic이 추후에 Objective-C 런타임과 떨어질 수 있다고 함
 - (SE-0160)
  45. 45. letswift(17) Codable
  46. 46. Before Swift4 struct Todo { var id: Int? var title: String var userId: Int var completed: Bool }
  47. 47. Before Swift4 struct Todo { var id: Int? var title: String var userId: Int var completed: Bool init?(json: [String: Any]) { guard let title = json["title"] as? String, let id = json["id"] as? Int, let userId = json["userId"] as? Int, let completed = json["completed"] as? Bool else { return nil } self.title = title self.userId = userId self.completed = completed self.id = id } }
  48. 48. Codable struct Todo: Codable { var id: Int? var title: String var userId: Int var completed: Bool }
  49. 49. Codable let dict = [ "id": 1, "title": "Let's Swift 준비", "userId": 1, "completed": false ] as [String: Any] do { let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) let todo = try JSONDecoder().decode(Todo.self, from: data) print(todo.title) } catch { }
  50. 50. Before Swift4 struct Todo { var id: Int? var title: String var userId: Int var completed: Bool func toJSON() -> [String: Any] { var json = [String: Any]() json["title"] = title json["userId"] = userId json["completed"] = completed if let id = id { json["id"] = id } return json } }
  51. 51. Before Swift4 let urlRequest = URLRequest(url: URL(string: “http:// letswift/api")!) do { let jsonTodo = try JSONSerialization.data(withJSONObject: todo.toJSON(), options: []) urlRequest.httpBody = jsonTodo }
  52. 52. Codable let urlRequest = URLRequest(url: URL(string: “http:// letswift.com/api")!) let encoder = JSONEncoder() do { let todo = Todo(id: nil, title: "Let's Swift 준비", userId: 1, completed: false) let json = try encoder.encode(todo) urlRequest.httpBody = json } catch { }
  53. 53. Nested, Codable struct Address: Codable { let city: String let zipcode: String } struct User: Codable { let id: Int? let name: String let email: String let address: Address }
  54. 54. Decodable struct Developer: Decodable { let id: Int let fullName: String let iOS: Bool } let json = """ { "id": 123456, "fullName": "Kim Younghoo", "iOS": false } """.data(using: .utf8)! let dev = try JSONDecoder().decode(Developer.self, from: json) print(dev)
  55. 55. https://developer.apple.com/documentation/swift/ decodable
  56. 56. init(from: Decoder) Required???
  57. 57. Compiler Magic!
  58. 58. Decodable struct Developer { let id: Int let fullName: String let iOS: Bool } extension Developer: Decodable { enum DeveloperKeys: String, CodingKey { case fullName case id case iOS } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: DeveloperKeys.self) let fullName: String = try container.decode(String.self, forKey: .fullName) let id: Int = try container.decode(Int.self, forKey: .id) let iOS: Bool = try container.decode(Bool.self, forKey: .iOS) self.init(id: id, fullName: fullName, iOS: iOS) } }
  59. 59. Array let json = """ [{ "fullName": "Kim Younghoo", "id": 123, "iOS": true, },{ "fullName": "Yoo Yongha", "id": 789, "iOS": false, }] """.data(using: .utf8)! let structArray = try JSONDecoder().decode([Developer].self, from: json) structArray.forEach { print($0) }
  60. 60. Dictionary let json = """ { "one": { "fullName": "Kim Younghoo", "id": 123, "iOS": true, }, "two": { "fullName": "Yoo Yongha", "id": 789, "iOS": false, } } """.data(using: .utf8)! let dict = try JSONDecoder().decode([String: Developer].self, from: json) dict.forEach { print($0) }
  61. 61. Change Key Names struct Developer: Decodable { let id: Int let fullName: String let iOS: Bool private enum CodingKeys: String, CodingKey { case id = "developer_id" case fullName case iOS = "is_iOS" } } let json = """ { "developer_id": 123456, "fullName": "Kim Younghoo", "is_iOS": false } """.data(using: .utf8)! let dev = try JSONDecoder().decode(Developer.self, from: json)
  62. 62. Play with “Using JSON with Custom Types” Playground
  63. 63. letswift(17) Swift 5.0
  64. 64. Swift 5.0 Late 2018 Rust-inspired memory ownership model Syntactic additions Groundwork for a new concurrency model • Non-goal for Swift 5 • maybe async/await
  65. 65. 감사합니다

×