Post

Replies

Boosts

Views

Activity

Manipulating SwiftUI view state in a Task closure (button action)
In the session Discover concurrency in SwiftUI (at 19:48), the following sample code is presented as an example of starting an async task from a Button action (which is synchronous): struct SavePhotoButton: View { var photo: SpacePhoto @State private var isSaving = false var body: some View { Button { Task { isSaving = true await photo.save() isSaving = false } } label: { Text("Save") // … } // … } } (The code on the slide uses async { … }. I replaced this with the current Task { … } syntax.) I'm wondering if manipulating view state from inside the task closure like this is allowed. In fact, when you compile this with -Xfrontend -warn-concurrency, you get compiler warnings on all three lines in the task closure: Task { // warning: Cannot use parameter 'self' with a non-sendable type 'SavePhotoButton' from concurrently-executed code isSaving = true // same warning await photo.save() // same warning isSaving = false } You have to mark the view as @MainActor to get rid of the warnings: @MainActor struct SavePhotoButton: View { … } Questions: Can you confirm that the sample code is invalid without the @MainActor annotation on the view? How does the Task { … } closure guarantees that it runs on the main actor. I know that Task { … } inherits the current actor execution context, but how does that work here? My guess: View.body is annotated with @MainActor in the SwiftUI module interface Actor context inheritance is based on the lexical scope, so the fact that the Task { … } closure is inside body is enough for it to inherit that context, even if it's called from another context. Is this correct? Thanks.
0
0
1.9k
Nov ’21
Multiline Text in a List on macOS
Environment: macOS 11.0 beta 2, Xcode 12.0 beta 2. I want to display a long Text inside a List with multiple lines without truncation. Here's my code: import PlaygroundSupport import SwiftUI struct ContentView: View {   var body: some View {     List {       Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")     }   } } let view = ContentView()   .frame(width: 250) PlaygroundPage.current.setLiveView(view) This code does the thing I want (multiline text) on iOS, but on macOS, the text is only a single line and truncated. You can paste this code into a playground to try it out. If I replace the List with VStack, the text is rendered in multiple lines, so it seems List on macOS disables this behavior. Here are a few modifiers I tried, but none achieves my desired result: Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")   .lineLimit(nil)   .multilineTextAlignment(.leading) Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")   .fixedSize(horizontal: false, vertical: true) Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")   .frame(idealHeight: .infinity) Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")   .frame(idealHeight: .greatestFiniteMagnitude)
0
0
727
Jul ’20