SwiftUI

Jan 3, 2020

Icon

Image(systemName: "star.fill").imageScale(.medium).foregroundColor(.yellow)

Bool

bool.toggle()

Binding

@State private var isPlaying: Bool = false

PlayButton(isPlaying: $isPlaying)
struct PlayButton : View {

@Binding var isPlaying: Bool

OnReceive

.onReceive(PodcastPlayer.currentTimePublisher) { newCurrentTime in
  self.currentTime = newCurrentTime
}

Weak

DispatchQueue.main.async { [weak self] in
DispatchQueue.global(qos: .background).async { [weak self] in
  guard let strongSelf = self else { return }

weak var owner: Person?

https://www.appcoda.com/memory-management-swift/

Product > Profile > Leaks

UI Tweaking

.padding([.leading, .trailing])
.font(.caption)

HStack {
 Text("Delicious")
 Image("20x20_avocado")
 Text("Avocado Toast").layoutPriority(1) // so it will not be compressed when HStack width is not enough
}
.lineLimit(1)

237_building_custom_views_with_swiftui.pdf

// Animation and draw grphaic

List(previousOrders) { order in
 HStack {
 VStack(alignment: .leading) {
 Text(order.summary)
 Text(order.purchaseDate)
 .font(.subheadline)
 .foregroundColor(.secondary)
 }
 Spacer()
 if order.includeSalt {
 SaltIcon()
 }
 }
}

struct IconOrientationEditor : View {
 let flipped: Bool
 var body: some View {
 ZStack {
 Color.gray
 AppIcon()
 .rotationEffect(.degrees(flipped ? 180 : 0))
 }
 }
}

Form {
 Button(action: submitOrder) { Text("Order") }
 Section(header: ) { Text("Avocado Toast").font(.title)
 }.
 Toggle(isOn: $order.includeSalt) { }
 Toggle(isOn: $order.includeRedPepperFlakes) { }
 Stepper(value: $order.quantity, in: 1...10) { }
 }
 Section {
 Button(action: submitOrder) { Text("Order") }
 }
}

Button(action: submitOrder) {
 VStack {
 Image("Toast")
 Text("Order")
 }
}

@State private var order: Order
struct Order {

enum Spread : CaseIterable, Hashable, Identifiable {
 case none
 case almondButter
 case peanutButter
 case honey
 case almou
 case tapenade
 case hummus
 case mayonnaise
 case kyopolou
 case adjvar
 case pindjur
 case vegemite
 case chutney
 case cannedCheese
 case feroce
 case kartoffelkase
 case tartarSauce
}
Picker(selection: $order.spread, label: Text("Spread")) {
 ForEach(Spread.allCases) { spread in
 Text(spread.name).tag(spread)
 }.
}

Button(action: submitOrder) { Text("Order") }
 .disabled(order.quantity == 0)
Toggle(isOn: $order.includeSalt) {}

Form {}
.accentColor(Color("avocadoGreen"))
.disabled(!connectedToToastNetwork)

216_swiftui_essentials.pdf

Combine

@Published var username: String = ""
var validatedUsername: AnyPublisher<String?, Never> {
 return $username
 .debounce(for: 0.5, scheduler: RunLoop.main)
 .removeDuplicates()
 .flatMap { username in
 return Future { promise in
 self.usernameAvailable(username) { available in
 promise(.success(available ? username : nil))
 }
 }
 }
 .eraseToAnyPublisher()
}

@Published var password: String = ""
@Published var passwordAgain: String = ""
var validatedPassword: AnyPublisher<String?, Never> {
 return CombineLatest($password, $passwordAgain) { password, passwordAgain in
 guard password == passwordAgain, password.count > 8 else { return nil }
 return password
 }
 .map { $0 == "password1" ? nil : $0 }
 .eraseToAnyPublisher()
}

var validatedCredentials: AnyPublisher<(String, String)?, Never> {
 return CombineLatest(validatedUsername, validatedPassword) { username, password in
 guard let uname = username, let pwd = password else { return nil }
 return (uname, pwd)
 }
 .eraseToAnyPublisher()
}

@IBOutlet var signupButton: UIButton!
var signupButtonStream: AnyCancellable?
override func viewDidLoad() {
 super.viewDidLoad()
 self.signupButtonStream = self.validatedCredentials
 .map { $0 != nil }
 .receive(on: RunLoop.main)
 .assign(to: \.isEnabled, on: signupButton)
}

Resources


[back]