Uploaded image for project: 'Swift'
  1. Swift
  2. SR-14764

`@MainActor` ignored by the compiler

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Medium
    • Resolution: Unresolved
    • Component/s: Compiler
    • Labels:
      None
    • Environment:

      Version 13.0 beta (13A5154h)
      swift-driver version: 1.26 Apple Swift version 5.5 (swiftlang-1300.0.19.104 clang-1300.0.18.4)
      Target: arm64-apple-macosx11.0

      Description

      Compiler seems to ignore `@MainActor` in the following code example:

       

      import SwiftUI
      
      class Model: ObservableObject {
        @Published
        var data: Data?
      }
      
      struct TestView: View {
        @ObservedObject
        var _model = Model()
      
        @MainActor
        func apply(_ data: Data) {
          // runtime warning:
          // Publishing changes from background threads is not allowed; make
          // sure to publish values from the main thread (via operators like
          // receive(on:)) on model updates.
      
          _model.data = data
      
          // runtime crash
          dispatchPrecondition(condition: .onQueue(.main))
        }
      
        func fetchData() async throws {
          let urlString = "https://google.com"
          guard case let url? = URL(string: urlString) else {
            return
          }
          let (data, response) = try await URLSession.shared.data(from: url)
          guard
            case let httpResponse? = response as? HTTPURLResponse,
            httpResponse.statusCode == 200
          else {
            return
          }
      
          // note there is NO `await` here as the compiler does not ask for it at all
          apply(data)
        }
      
        var body: some View {
          Text("\(_model.data.map(\.count) ?? 0)")
            .task {
              do {
                try await fetchData()
              } catch {
                print(error)
              }
            }
        }
      }
      

      I can try adding `await` infant of the `apply` call, but this results into a `No 'async' operations occur within 'await' expression` warning.

      I can apply two workarounds:

      • Make `apply(_: )` method `async` and add `await` infant of it as the compiler correctly would ask for, but this doesn't make sense as this should be a non-suspendible synchronous method just to hop back to the main thread and sign the value.
      • I can move `@MainActor` to the entire type and make `fetchData` as `nonisolated`, which works as intended, but the original example should also work and require the `await` keyword.

      Discussion on the forum: https://forums.swift.org/t/mainactor-ignored-by-the-compiler/49533

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            DevAndArtist Adrian Meister
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated: