SE-0247
SE-0245
SE-0255
SE-0244
SE-0251
SE-0252
SE-0242
SE-0258
SE-0254
SE-0260
SE-0261
SE-0244
SE-0255
SE-0258
SE-0261
SE-0255
SE-0244
SE-0261
Implicit returns from single-expression functions
Opaque Result Types
Identifiable Protocol
SE-0258 Property Wrappers
Implicit returns from single-
expression functions
SE-0255
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 }
functionsImplicit returns from
func sum(_ lhs: Int, _ rhs: Int) -> Int {
return lhs + rhs
}1
functionsImplicit returns from
func sum(_ lhs: Int, _ rhs: Int) -> Int {
lhs + rhs
}1
functionsImplicit returns from
func sum(_ lhs: Int, _ rhs: Int) -> Int {
let result = lhs + rhs
result
}1
Implicit returns from functionssingle-expression
func sum(_ lhs: Int, _ rhs: Int) -> Int {
let result = lhs + rhs
result
}1
Implicit returns from functionssingle-expression
func sum(_ lhs: Int, _ rhs: Int) -> Int {
let result = lhs + rhs
return result
}1
Computed property
struct ContentView: View {
var body: some View {
Text("Hello world!")
}1
}1
Computed property
struct ContentView: View {
var body: some View {
let text = "Hello world!"
Text(text)
}1
}1
struct ContentView: View {
var body: some View {
let text = "Hello world!"
return Text(text)
}1
}1
Computed property
Single-expression
struct ContentView: View {
var body: some View {
Text("Hello world!").font(.title).bold()
}1
}1
Single-expression
struct ContentView: View {
var body: some View {
Text("Hello world!")
.font(.title)
.bold()
}1
}1
Evaluating an expression
• Returns a value
• Causes a side effect
• Both
• Ternary Conditional Operator
Expression vs Statement
return .random() ? true : false
if .random() {
return true
} else {
return false
}
• If - else
• Ternary Conditional Operator
Expression vs Statement
return .random() ? true : false
if .random() {
return true
} else {
return false
}
• If - else
Expression
Statement
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
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
• Function,Computed property
Implicit returns from single-expression functionsSE-0255
• Single-expression
• Implicit return
Opaque Result Types
SE-0244
some
struct ContentView: View {
var body: some View {1
Text("Hello SwiftUI!")
}1
}1
without some
struct ContentView: View {
var body: View {1
Text("Hello SwiftUI!")
}1
}1
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
View return type
var body: Text {1
Text("Hello SwiftUI!")
}1
View return type
var body: Text {1
Text("Hello SwiftUI!")
.foregroundColor(.white)
.background(Color.black)
}1
var body:
ModifiedContent<Text, _BackgroundModifier<Color>>
{1
Text("Hello SwiftUI!")
.foregroundColor(.white)
.background(Color.black)
}1
View return type
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
var body: some View {1
VStack {2
Image("SwiftUI")
.resizable()
.scaledToFit()
Text("Hello SwiftUI!")
.foregroundColor(.white)
.background(Color.black)
}.padding()
}3
Opaque type
func genericFunction<T: Animal>(_ animal: T) {
... // Callee - abstracted type
}
// T == Dog, Caller pick the type
genericFunction(Dog())
Abstracted type - Generic
// T == Cat
genericFunction(Cat())
func opaqueTypeFunction() -> some Animal {
Dog() // Callee pick the type
}
// Caller - abstracted type
let animal: some Animal = opaqueTypeFunction()
Abstracted type - Opaque type
Protocol return type
func protocolReturnType() -> Animal {
.random() ? Dog() : Cat()
}
// Dog? Cat?
let animal: Animal = protocolReturnType()
Self or associated type
func someFunction(
lhs: Equatable,
rhs: Equatable
) -> Bool { ... }
func someFunction() -> Hashable { ... }
var someProperty: Collection { ... }
Type identity
func returnConcreteType() -> some Animal {
let result: Animal = Dog()
return result
}
func returnConcreteType() -> some Animal {
Dog()
}
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")
Type identity
func opaqueTypeFunc() -> some Equatable {
.random() ? "Swift" : 5.1
}
func opaqueTypeFunc() -> some Equatable {
// Callee pick the type
// Same return type
.random() ? "Swift" : "UI"
}
var body: some View {
.random()
? Rectangle()
: Circle()
}
SwiftUI
var body: some View {
.random()
? AnyView(Rectangle())
: AnyView(Circle())
}
• Hiding type information
Opaque Result TypesSE-0244
• Preserving type information
• Reverse generic
Identifiable Protocol
SE-0261
struct Animal: Equatable {1
let name: String
let age: Int
}1
let 🐶 = Animal(name: " ", age: 5)
let 🐰 = Animal(name: " ", age: 5)
Equatable
🐶 == 🐰 // true
struct Animal: Equatable {1
let name: String
let age: Int
}1
Equatable
struct Animal: Equatable {1
let id: Int
let name: String
let age: Int
}1
Equatable
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)
Equatable
// false
🐶𝞪 == 🐶𝞫
// true
🐶𝞪.id == 🐶𝞫.id
Equatable
// false
🐶𝞪 == 🐶𝞫
// true
🐶𝞪.id == 🐶𝞫.id
// Identity Operator, Reference type
🐶𝞪 === 🐶𝞫
Identifiable Protocol
protocol Identifiable {
associatedtype ID : Hashable
var id: Self.ID { get }
}
Identifiable Protocol
protocol Identifiable {
associatedtype ID : Hashable
var id: Self.ID { get }
}
extension Animal: Identifiable {}
Diff algorithm
let 🐶𝞪 = Animal(id: 1, name: " ", age: 5)
let 🐶𝞫 = Animal(id: 1, name: " ", age: 6)
...
let 🐶𝞬 = Animal(id: 1, name: " ", age: 10)
...
🐶𝞪 <---> 🐶𝞫 <---> 🐶𝞬
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
}
SwiftUI
ForEach(["Data1", "Data2", "Data3"], id: .self)
ForEach([🐶, 🐱, 🐰], id: .id)
SwiftUI
ForEach([🐶, 🐱, 🐰])
ForEach(["Data1", "Data2", "Data3"], id: .self)
ForEach([🐶, 🐱, 🐰], id: .id)
SwiftUI
ForEach([🐶, 🐱, 🐰]) { ... }
let 🐶 = Animal(id: 1, name: " ", age: 5)
let 🐱 = Animal(id: 2, name: " ", age: 2)
let 🐰 = Animal(id: 3, name: " ", age: 3)
SwiftUI
ForEach([🐶, 🐱, 🐰]) { ... }
let 🐶 = Animal(id: 1, name: " ", age: 5)
let 🐱 = Animal(id: 1, name: " ", age: 2)
let 🐰 = Animal(id: 1, name: " ", age: 3)
SwiftUI
ForEach([🐶, 🐱, 🐰]) { ... }
let 🐶 = Animal(id: 1, name: " ", age: 5)
let 🐱 = Animal(id: 1, name: " ", age: 2)
let 🐰 = Animal(id: 1, name: " ", age: 3)
• Distinguish the identity of an entity from the state
Identifiable ProtocolSE-0261
• Identify changes to the state
• Value type identity
Property Wrappers
SE-0258
struct ContentView: View {
@State private var isOn: Bool = false
var body: some View {
Toggle(isOn: $isOn) { Text("Label") }
}
}
SwiftUI
struct ContentView: View {
@State private var isOn: Bool = false
var body: some View {
Toggle(isOn: $isOn) { Text("Label") }
}
}
SwiftUI
@State
@Binding
@ObservedObject
@EnvironmentObject
@Environment
@IBOutlet
@NSCopying
@available
@objc
lazy
...
Attributes
struct SomeType {
var someValue = 0
lazy var someLazyValue = self.someValue + 1
}1
lazy
struct SomeType {
var someValue = 0
lazy var someLazyValue = self.someValue + 1
lazy var anotherLazyValue = self.someValue * 2
}1
lazy
Boilerplate
var isLoggedIn: Bool {
get {
UserDefaults.standard.bool(forKey: "IS_LOGGED_IN")
}
set {
UserDefaults.standard.set(newValue, forKey: "IS_LOGGED_IN")
}
}
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")
}
}
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)
}
}
}
Custom attribute
struct User {
@UserDefault(key: "IS_LOGGED_IN")
var isLoggedIn: Bool
@UserDefault(key: "IS_FIRST_LOGIN")
var isFirstLogin: Bool
}
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)
Synthesized property
@UserDefault(key: "IS_LOGGED_IN")
var isLoggedIn: Bool
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
Synthesized property
struct UserDefault<Value> {
var projectedValue: Self {
get { self }
set { self = newValue }
}
}
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 }
}
}
Synthesized property
isLoggedIn // Computed Property
_isLoggedIn // Stored Property, Private
$isLoggedIn // Computed Property, Optional
@UserDefault(key: "IS_LOGGED_IN")
var isLoggedIn: Bool
• Allow defining patterns for properties
Property WrappersSE-0258
• Provides the storage for a property
• Eliminate boilerplate code
Swift in SwiftUI
Swift in SwiftUI
Swift in SwiftUI

Swift in SwiftUI