iosswiftuixcode15swift6

How do I reference a 'shared' static property from a non-isolated context?


I am working on a map app in Xcode 15.4.

Everything works except when I reference the @MainActor class LocationManager {} in the private var locationManager

I get the following error:

Main actor-isolated static property 'shared' can not be referenced from a non-isolated context; this is an error in Swift 6

I am new to Swift 6 and could use some guidance resolving this issue.

Here is the code:

import SwiftUI
import MapKit

@MainActor class LocationManager {
    static let shared = LocationManager()
    let manager: CLLocationManager
    
    init() {
        self.manager = CLLocationManager()
        if self.manager.authorizationStatus == .notDetermined {
            self.manager.requestWhenInUseAuthorization()
        }
    }
}

extension CLLocationCoordinate2D {
    static var notreDam: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: 48.853218898078126, longitude:2.349977679044624)
    }
    
    static var saintGermain: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: 48.854184067183304, longitude:2.334469956279526)
    }
    
    static var saintDenis: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: 48.93693647702151, longitude:2.3565013545150872)
    }
    
    static var saintEustach: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: 48.86350319977858, longitude:2.345539521410205)
    }
    
    static var saintEtienne: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: 48.846708620929796, longitude: 2.34847593490404)
    }
    
}

enum MapOptions: String, Identifiable, CaseIterable {
    case standard
    case hybrid
    case imagery
    
    var id: String {
        self.rawValue
    }
    
    var mapStyle: MapStyle {
        switch self {
        case .standard:
            return .standard
        case .hybrid:
            return .hybrid
        case .imagery:
            return .imagery
        }
    }
}

struct ContentView: View {
    
    private var locationManager = LocationManager.shared
    @State private var selectedMapOption: MapOptions = .standard
    
    var body: some View {
        ZStack(alignment: .top) {
            Map {
                Annotation("Notre Dame", coordinate: .notreDam) {
                    Image(systemName: "house.circle.fill")
                        .padding(4)
                        .background(.red)
                        .foregroundColor(.white)
                        .cornerRadius(20.0)
                }
                
                Annotation("Saint Germain", coordinate: .saintGermain) {
                    Image(systemName: "house.circle.fill")
                        .padding(4)
                        .background(.red)
                        .foregroundColor(.white)
                        .cornerRadius(20.0)
                }
                
                Annotation("Saint Denis", coordinate: .saintDenis) {
                    Image(systemName: "house.circle.fill")
                        .padding(4)
                        .background(.red)
                        .foregroundColor(.white)
                        .cornerRadius(20.0)
                }
                
                Annotation("Saint Eustache", coordinate: .saintEustach) {
                    Image(systemName: "house.circle.fill")
                        .padding(4)
                        .background(.red)
                        .foregroundColor(.white)
                        .cornerRadius(20.0)
                }
                
                Annotation("Saint Etienne", coordinate: .saintEtienne) {
                    Image(systemName: "house.circle.fill")
                        .padding(4)
                        .background(.red)
                        .foregroundColor(.white)
                        .cornerRadius(20.0)
                }
                
                UserAnnotation()
                
            }.mapStyle(selectedMapOption.mapStyle)
            Picker("Map Styles", selection: $selectedMapOption) {
                ForEach(MapOptions.allCases) { mapOption in
                    Text(mapOption.rawValue.capitalized).tag(mapOption)
                }
            }.pickerStyle(.segmented)
                .background(.white)
                .padding()
        }
    }
}

#Preview {
    ContentView()
}

Solution

  • One easy way is to annotate the ContentView with @MainActor - thus the context where the shared instance is used becomes main actor-isolated.

    When you move to Xcode 16 and Swift 6, View is marked with @MainActor so this warning will be gone by then.

    See What’s new in SwiftUI - WWDC 2024 around 17:30.