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.

Swift in SwiftUI

139 views

Published on

Swift in SwiftUI for LetSwift 2019
- The Swift 5.1 features in SwiftUI

Published in: Mobile
  • Be the first to comment

  • Be the first to like this

Swift in SwiftUI

  1. 1. SE-0247 SE-0245 SE-0255 SE-0244 SE-0251 SE-0252 SE-0242 SE-0258 SE-0254 SE-0260 SE-0261
  2. 2. SE-0244 SE-0255 SE-0258 SE-0261
  3. 3. SE-0255 SE-0244 SE-0261 Implicit returns from single-expression functions Opaque Result Types Identifiable Protocol SE-0258 Property Wrappers
  4. 4. Implicit returns from single- expression functions SE-0255
  5. 5. closuresImplicit returns from let sum = { (lhs: Int, rhs: Int) in lhs + rhs } [1, 2, 3, 4, 5] .map { $0 * 2 } [true, false, true] .filter { $0 }
  6. 6. functionsImplicit returns from func sum(_ lhs: Int, _ rhs: Int) -> Int { return lhs + rhs }1
  7. 7. functionsImplicit returns from func sum(_ lhs: Int, _ rhs: Int) -> Int { lhs + rhs }1
  8. 8. functionsImplicit returns from func sum(_ lhs: Int, _ rhs: Int) -> Int { let result = lhs + rhs result }1
  9. 9. Implicit returns from functionssingle-expression func sum(_ lhs: Int, _ rhs: Int) -> Int { let result = lhs + rhs result }1
  10. 10. Implicit returns from functionssingle-expression func sum(_ lhs: Int, _ rhs: Int) -> Int { let result = lhs + rhs return result }1
  11. 11. Computed property struct ContentView: View { var body: some View { Text("Hello world!") }1 }1
  12. 12. Computed property struct ContentView: View { var body: some View { let text = "Hello world!" Text(text) }1 }1
  13. 13. struct ContentView: View { var body: some View { let text = "Hello world!" return Text(text) }1 }1 Computed property
  14. 14. Single-expression struct ContentView: View { var body: some View { Text("Hello world!").font(.title).bold() }1 }1
  15. 15. Single-expression struct ContentView: View { var body: some View { Text("Hello world!") .font(.title) .bold() }1 }1
  16. 16. Evaluating an expression • Returns a value • Causes a side effect • Both
  17. 17. • Ternary Conditional Operator Expression vs Statement return .random() ? true : false if .random() { return true } else { return false } • If - else
  18. 18. • Ternary Conditional Operator Expression vs Statement return .random() ? true : false if .random() { return true } else { return false } • If - else Expression Statement
  19. 19. Expression vs Statement var body: some View { .random() ? Text("true") : Text("false") }1 var body: some View { if .random() { Text("true") } else { Text("false") } } • Ternary Conditional Operator • If - else Expression Statement
  20. 20. Expression vs Statement var body: some View { .random() ? Text("true") : Text("false") }1 var body: some View { if .random() { return Text("true") } else { return Text("false") } } • Ternary Conditional Operator • If - else Expression Statement
  21. 21. • Function,Computed property Implicit returns from single-expression functionsSE-0255 • Single-expression • Implicit return
  22. 22. Opaque Result Types SE-0244
  23. 23. some struct ContentView: View { var body: some View {1 Text("Hello SwiftUI!") }1 }1
  24. 24. without some struct ContentView: View { var body: View {1 Text("Hello SwiftUI!") }1 }1
  25. 25. Error - View has associated type struct ContentView: View { var body: View { Text("Hello SwiftUI!") }1 }1 protocol View { associatedtype Body : View var body: Self.Body { get } }1
  26. 26. View return type var body: Text {1 Text("Hello SwiftUI!") }1
  27. 27. View return type var body: Text {1 Text("Hello SwiftUI!") .foregroundColor(.white) .background(Color.black) }1
  28. 28. var body: ModifiedContent<Text, _BackgroundModifier<Color>> {1 Text("Hello SwiftUI!") .foregroundColor(.white) .background(Color.black) }1 View return type
  29. 29. var body: ModifiedContent<VStack<TupleView<(ModifiedContent<I mage, _AspectRatioLayout>, ModifiedContent<Text, _BackgroundModifier<Color>>)>>, _PaddingLayout> {1 VStack {2 Image("SwiftUI") .resizable() .scaledToFit() Text("Hello SwiftUI!") .foregroundColor(.white) .background(Color.black) }.padding() }3 View return type
  30. 30. var body: some View {1 VStack {2 Image("SwiftUI") .resizable() .scaledToFit() Text("Hello SwiftUI!") .foregroundColor(.white) .background(Color.black) }.padding() }3 Opaque type
  31. 31. func genericFunction<T: Animal>(_ animal: T) { ... // Callee - abstracted type } // T == Dog, Caller pick the type genericFunction(Dog()) Abstracted type - Generic // T == Cat genericFunction(Cat())
  32. 32. func opaqueTypeFunction() -> some Animal { Dog() // Callee pick the type } // Caller - abstracted type let animal: some Animal = opaqueTypeFunction() Abstracted type - Opaque type
  33. 33. Protocol return type func protocolReturnType() -> Animal { .random() ? Dog() : Cat() } // Dog? Cat? let animal: Animal = protocolReturnType()
  34. 34. Self or associated type func someFunction( lhs: Equatable, rhs: Equatable ) -> Bool { ... } func someFunction() -> Hashable { ... } var someProperty: Collection { ... }
  35. 35. Type identity func returnConcreteType() -> some Animal { let result: Animal = Dog() return result } func returnConcreteType() -> some Animal { Dog() }
  36. 36. Type identity func genericFunc<T: Equatable>( lhs: T, rhs: T ) -> Bool { lhs == rhs // Same generic type T } // Caller pick the type genericFunction(lhs: "Swift", rhs: "UI")
  37. 37. Type identity func opaqueTypeFunc() -> some Equatable { .random() ? "Swift" : 5.1 } func opaqueTypeFunc() -> some Equatable { // Callee pick the type // Same return type .random() ? "Swift" : "UI" }
  38. 38. var body: some View { .random() ? Rectangle() : Circle() } SwiftUI var body: some View { .random() ? AnyView(Rectangle()) : AnyView(Circle()) }
  39. 39. • Hiding type information Opaque Result TypesSE-0244 • Preserving type information • Reverse generic
  40. 40. Identifiable Protocol SE-0261
  41. 41. struct Animal: Equatable {1 let name: String let age: Int }1 let 🐶 = Animal(name: " ", age: 5) let 🐰 = Animal(name: " ", age: 5) Equatable 🐶 == 🐰 // true
  42. 42. struct Animal: Equatable {1 let name: String let age: Int }1 Equatable
  43. 43. struct Animal: Equatable {1 let id: Int let name: String let age: Int }1 Equatable
  44. 44. struct Animal: Equatable { let id: Int let name: String let age: Int } Equatable let 🐶𝞪 = Animal(id: 1, name: " ", age: 5) let 🐶𝞫 = Animal(id: 1, name: " ", age: 6)
  45. 45. Equatable // false 🐶𝞪 == 🐶𝞫 // true 🐶𝞪.id == 🐶𝞫.id
  46. 46. Equatable // false 🐶𝞪 == 🐶𝞫 // true 🐶𝞪.id == 🐶𝞫.id // Identity Operator, Reference type 🐶𝞪 === 🐶𝞫
  47. 47. Identifiable Protocol protocol Identifiable { associatedtype ID : Hashable var id: Self.ID { get } }
  48. 48. Identifiable Protocol protocol Identifiable { associatedtype ID : Hashable var id: Self.ID { get } } extension Animal: Identifiable {}
  49. 49. Diff algorithm let 🐶𝞪 = Animal(id: 1, name: " ", age: 5) let 🐶𝞫 = Animal(id: 1, name: " ", age: 6) ... let 🐶𝞬 = Animal(id: 1, name: " ", age: 10) ... 🐶𝞪 <---> 🐶𝞫 <---> 🐶𝞬
  50. 50. SwiftUI extension List { init<Data, RowContent>(_ data: Data, ... ) where Data.Element : Identifiable } extension View { func alert<Item>(item: Binding<Item?>, ... ) -> some View where Item : Identifiable }
  51. 51. SwiftUI ForEach(["Data1", "Data2", "Data3"], id: .self) ForEach([🐶, 🐱, 🐰], id: .id)
  52. 52. SwiftUI ForEach([🐶, 🐱, 🐰]) ForEach(["Data1", "Data2", "Data3"], id: .self) ForEach([🐶, 🐱, 🐰], id: .id)
  53. 53. SwiftUI ForEach([🐶, 🐱, 🐰]) { ... } let 🐶 = Animal(id: 1, name: " ", age: 5) let 🐱 = Animal(id: 2, name: " ", age: 2) let 🐰 = Animal(id: 3, name: " ", age: 3)
  54. 54. SwiftUI ForEach([🐶, 🐱, 🐰]) { ... } let 🐶 = Animal(id: 1, name: " ", age: 5) let 🐱 = Animal(id: 1, name: " ", age: 2) let 🐰 = Animal(id: 1, name: " ", age: 3)
  55. 55. SwiftUI ForEach([🐶, 🐱, 🐰]) { ... } let 🐶 = Animal(id: 1, name: " ", age: 5) let 🐱 = Animal(id: 1, name: " ", age: 2) let 🐰 = Animal(id: 1, name: " ", age: 3)
  56. 56. • Distinguish the identity of an entity from the state Identifiable ProtocolSE-0261 • Identify changes to the state • Value type identity
  57. 57. Property Wrappers SE-0258
  58. 58. struct ContentView: View { @State private var isOn: Bool = false var body: some View { Toggle(isOn: $isOn) { Text("Label") } } } SwiftUI
  59. 59. struct ContentView: View { @State private var isOn: Bool = false var body: some View { Toggle(isOn: $isOn) { Text("Label") } } } SwiftUI @State @Binding @ObservedObject @EnvironmentObject @Environment
  60. 60. @IBOutlet @NSCopying @available @objc lazy ... Attributes
  61. 61. struct SomeType { var someValue = 0 lazy var someLazyValue = self.someValue + 1 }1 lazy
  62. 62. struct SomeType { var someValue = 0 lazy var someLazyValue = self.someValue + 1 lazy var anotherLazyValue = self.someValue * 2 }1 lazy
  63. 63. Boilerplate var isLoggedIn: Bool { get { UserDefaults.standard.bool(forKey: "IS_LOGGED_IN") } set { UserDefaults.standard.set(newValue, forKey: "IS_LOGGED_IN") } }
  64. 64. Boilerplate var isLoggedIn: Bool { get { UserDefaults.standard.bool(forKey: "IS_LOGGED_IN") } set { UserDefaults.standard.set(newValue, forKey: "IS_LOGGED_IN") } } var isFirstLogin: Bool { get { UserDefaults.standard.bool(forKey: "IS_FIRST_LOGIN") } set { UserDefaults.standard.set(newValue, forKey: "IS_FIRST_LOGIN") } }
  65. 65. Wrapper Type @propertyWrapper struct UserDefault<Value> { let key: String var wrappedValue: Value? { get { UserDefaults.standard.object(forKey: key) as? Value } set { UserDefaults.standard.set(newValue, forKey: key) } } }
  66. 66. Custom attribute struct User { @UserDefault(key: "IS_LOGGED_IN") var isLoggedIn: Bool @UserDefault(key: "IS_FIRST_LOGIN") var isFirstLogin: Bool }
  67. 67. Custom attribute struct User { @UserDefault(key: "IS_LOGGED_IN") var isLoggedIn: Bool @UserDefault(key: "IS_FIRST_LOGIN") var isFirstLogin: Bool } var user = User() user.isLoggedIn = true user.isFirstLogin = false print(user.isLoggedIn ?? false) print(user.isFirstLogin ?? true)
  68. 68. Synthesized property @UserDefault(key: "IS_LOGGED_IN") var isLoggedIn: Bool
  69. 69. Synthesized property @UserDefault(key: "IS_LOGGED_IN") var isLoggedIn: Bool private var _isLoggedIn: UserDefault<Bool> = UserDefault<Bool>(key: "IS_LOGGED_IN") var isLoggedIn: Bool { get { _isLoggedIn.wrappedValue } set { _isLoggedIn.wrappedValue = newValue } } // Synthesized property
  70. 70. Synthesized property struct UserDefault<Value> { var projectedValue: Self { get { self } set { self = newValue } } }
  71. 71. Synthesized property struct UserDefault<Value> { var projectedValue: Self { get { self } set { self = newValue } } } struct User { var $isLoggedIn: UserDefault<Bool> { get { _isLoggedIn.projectedValue } set { _isLoggedIn.projectedValue = newValue } } }
  72. 72. Synthesized property isLoggedIn // Computed Property _isLoggedIn // Stored Property, Private $isLoggedIn // Computed Property, Optional @UserDefault(key: "IS_LOGGED_IN") var isLoggedIn: Bool
  73. 73. • Allow defining patterns for properties Property WrappersSE-0258 • Provides the storage for a property • Eliminate boilerplate code

×