SwiftUI changes in Xcode 11 Beta 4

SwiftUI iOS beta

iOS & iPadOS 13 Beta 4 just released today, let's see some highlight changes for SwiftUI, you can check the rest here.

color -> foregroundColor

The color(_:) modifier for Text is renamed foregroundColor(_:).

relativeWidth/Height/Size are gone 😦

The relativeWidth(_:), relativeHeight(_:), and relativeSize(width:height:) modifiers are deprecated. Apple suggests us to use other modifiers like frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:) instead.

I was shocked when these methods are gone, but the situation might not be that bad since I didn't use it that much and in my experienced designers never think in relative width/height, they always think padding and fixed size which already provided in SwiftUI. This is still in beta Apple might decide to bring it back if community ask for it.

BindableObject protocol

The BindableObject protocol’s requirement is now willChange instead of didChange, and should now be sent before the object changes rather than after it changes.

DatePicker deprecated initializers

Initializers with minimumDate and maximumDate are gone. Now we initialized it with ClosedRange, PartialRangeThrough, and PartialRangeFrom.

We use PartialRangeFrom for minimumDate.

DatePicker("Minimum Date",
selection: $selectedDate,
in: Date()...,
displayedComponents: [.date])

We use PartialRangeThrough for maximumDate.

DatePicker("Maximum Date",
selection: $selectedDate,
in: ...Date(),
displayedComponents: [.date])

If you want to enforce both minimumDate and maximumDate use ClosedRange

@State var selectedDate = Date()

var dateClosedRange: ClosedRange<Date> {
let min = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let max = Calendar.current.date(byAdding: .day, value: 1, to: Date())!
return min...max
}

DatePicker(
selection: $selectedDate,
in: dateClosedRange,
displayedComponents: [.hourAndMinute, .date],
label: { Text("Due Date") }
)

Collection protocol

The identified(by:) method on the Collection protocol is deprecated in favor of dedicated List's init(_:id:selection:rowContent:) and ForEach's init(_:id:content:) initializers.

So this code

let users = ["John", "Alice", "Bob"]

var body: some View {
List(users.identified(by: \.self)) { user in
NavigationLink(destination: Text("Detail for \(user)")) {
Text(user)
}
}.navigationBarTitle("List Example")
}

Would become something like

let users = ["John", "Alice", "Bob"]

var body: some View {
List(users, id: \.self) { user in
NavigationLink(destination: Text("Detail for \(user)")) {
Text(user)
}
}.navigationBarTitle("List Example")
}

Presentation

Alert, Modal, and ActionSheet have different syntax in the previous beta. This update brings consistency to these presentation methods. For keeping everything consistent, PresentationLink is deprecated.

struct PresentationExample: View {
@State var isPresented = false
@State var isActionSheet = false
@State var isAlert = false

var actionSheet: ActionSheet {
ActionSheet(title: Text("Action"),
message: Text("Description"),
buttons: [
.default(Text("OK"), onTrigger: {

}),
.destructive(Text("Delete"), onTrigger: {

})
]
)
}

var alert: Alert {
Alert(title: Text("Error"),
message: Text("Error Reason"),
dismissButton: .default(Text("OK"))
)
}

var modal: some View {
Text("Modal")
}

var body: some View {
VStack {
Button("Modal") {
self.isPresented = true
}
Button("Action Sheet") {
self.isActionSheet = true
}
Button("Alert Sheet") {
self.isAlert = true
}
}.sheet(isPresented: $isPresented, content: {
self.modal
})
.actionSheet(isPresented: $isActionSheet, content: {
actionSheet
}).alert(isPresented: $isAlert, content: {
alert
})

}
}

References

You can check out my compiled cheat sheet at fuckingswiftui.com or goshdarnswiftui.com if you want more work-friendly.


← Home