UIKit Internal bug: Unbalanced call to _endOcclusion, please file a feedback report with any information you have that helps reproduce this bug!

FB13206752

I’m using 2 different bottom sheets that the first one is showing up from my ContentView -> LocationRequestIsOnView -> ItemInfoView. LocationRequestIsOnView has a MapKit for showing Annotations of Point Of Interests. When the user tap on an Annotation ItemInfoView pops-up as a bottom sheet to be able to show details of the selected POI. The problem is exactly happening in this step. When the bottom sheet pops-up, I’m closing it through close icon button or using .onDisappear changing isShowingBottomSheet flag to false. As bottom sheet closing it’s immediately shows a large white view and then closing. In this point, I’m getting the following warning in Xcode log.

UIKit Internal bug: Unbalanced call to _endOcclusion, please file a feedback report with any information you have that helps reproduce this bug!

struct ContentView: View {
    @StateObject var locationManager = LocationManager()
    @EnvironmentObject private var inAppPurchaseManager: InAppPurchaseManager
    @Environment(\.requestReview) var requestReview
    
    @State private var visibleRegion: MKCoordinateRegion?
    @State private var searchResults: [MKMapItem] = []
    @State private var selectedResult: MKMapItem?
    @State private var route: MKRoute?
    @State private var selectedTabBarButton = ""
    @State var isShowingBottomSheet = false
    @State private var cameraPosition: MapCameraPosition = .userLocation(followsHeading: true, fallback: .automatic)
    @State var isLocationDeniedViewShown = false
    @State private var defaultSearchText = "EV Charging Points"
    
    private let onboardingTip = OnboardingTip()
    
    var body: some View {
        if locationManager.state == .notDetermined { // User doesn't give location and their first time open the app
            LocationRequestView()
                .task {
                    _ = Task {
                        do {
                            try await inAppPurchaseManager.loadProducts()
                        } catch {
                            print(error)
                        }
                    }
                }
        } else if locationManager.state == .denied && !isLocationDeniedViewShown { // User doesn't give location and isLocationDeniedViewShown is false
            LocationRequestDeniedView(isLocationDeniedViewShown: $isLocationDeniedViewShown)
                .task {
                    _ = Task {
                        do {
                            try await inAppPurchaseManager.loadProducts()
                        } catch {
                            print(error)
                        }
                    }
                }
        } else if locationManager.state == .denied && isLocationDeniedViewShown { // User doesn't give location and isLocationDeniedViewShown is true
            if !inAppPurchaseManager.hasUnlockedPro {
                VStack(spacing: 0) {
                    BannerAd(unitID: "ca-app-pub-2327375927149500/2020038616")
                        .background(Color.bannerBG)
                        .frame(maxWidth: .infinity, maxHeight: 50)
                }
                .frame(maxWidth: .infinity, maxHeight: 50)
                .background(Color.bannerBG)
                .padding(.bottom, -10)
            }
            
            LocationRequestDeniedMapView(
                cameraPosition: $cameraPosition,
                searchResults: $searchResults,
                selectedResult: $selectedResult,
                route: $route,
                visibleRegion: $visibleRegion,
                defaultSearchText: $defaultSearchText,
                isLocationDeniedViewShown: $isLocationDeniedViewShown,
                isShowingBottomSheet: $isShowingBottomSheet
            )
            .task {
                _ = Task {
                    do {
                        try await inAppPurchaseManager.loadProducts()
                    } catch {
                        print(error)
                    }
                }
            }
        } else { // User give location permission
            if !inAppPurchaseManager.hasUnlockedPro {
                VStack(spacing: 0) {
                    BannerAd(unitID: "ca-app-pub-2327375927149500/2020038616")
                        .background(Color.bannerBG)
                        .frame(maxWidth: .infinity, maxHeight: 50)
                }
                .frame(maxWidth: .infinity, maxHeight: 50)
                .background(Color.bannerBG)
                .padding(.bottom, -10)
            }
            
            LocationRequestIsOnView(
                cameraPosition: $cameraPosition,
                searchResults: $searchResults,
                selectedResult: $selectedResult,
                route: $route,
                visibleRegion: $visibleRegion,
                defaultSearchText: $defaultSearchText,
                isLocationDeniedViewShown: $isLocationDeniedViewShown,
                isShowingBottomSheet: $isShowingBottomSheet
            )
            .task {
                _ = Task {
                    do {
                        try await inAppPurchaseManager.loadProducts()
                    } catch {
                        print(error)
                    }
                }
            }
        }
    }
}

struct POIButtons: View {
    @Binding var searchResults: [MKMapItem]
    @Binding var selectedTabBarButton: String
    @Binding var visibleRegion: MKCoordinateRegion?
    @Binding var route: MKRoute?
    @Binding var isShowingBottomSheet: Bool
    @Binding var defaultSearchText: String
    @StateObject var locationManager = LocationManager.shared
    @State var showSettingsView: Bool = false
    
    var body: some View {
        HStack {
            evStationButton
            gasStationButton
            NavigationStack {
                settingsButton
            }
        }
        .onAppear(perform: {
            if locationManager.state == .denied {
                search(for: defaultSearchText)
            }
        })
        .labelStyle(AdaptiveLabelStyle())
    }
    
    var evStationButton: some View {
        Button("EV Station", systemImage: "bolt.car") {
            search(for: "EV Charging Points")
            selectedTabBarButton = "EV"
            isShowingBottomSheet = false
            route = nil
        }
        .buttonStyle(PressedButtonStyle())
    }
    
    var gasStationButton: some View {
        Button("Gas Station", systemImage: "fuelpump.circle") {
            search(for: "Gas Station")
            selectedTabBarButton = "Gas"
            isShowingBottomSheet = false
            route = nil
        }
        .buttonStyle(PressedButtonStyle())
    }
    
    var settingsButton: some View {
        VStack {
            Button("Settings", systemImage: "gear.circle") {
                showSettingsView.toggle()
                selectedTabBarButton = "Settings"
                isShowingBottomSheet = false
                route = nil
            }
            .navigationDestination(
                isPresented: $showSettingsView) {
                    SettingsView(isShowingBottomSheet: $isShowingBottomSheet)
                }
                .buttonStyle(PressedButtonStyle())
        }
    }
    
    func search(for query: String) {
        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = query
        request.resultTypes = .pointOfInterest
        request.region = visibleRegion ?? MKCoordinateRegion(
            center: .userLocation,
            span: MKCoordinateSpan(latitudeDelta: 0.008, longitudeDelta: 0.008))
        Task {
            let search = MKLocalSearch(request: request)
            let response = try? await search.start ()
            searchResults = response?.mapItems ?? []
        }
    }
}

struct LocationRequestIsOnView: View {
    @State private var selectedTabBarButton = ""
    @Environment(\.requestReview) var requestReview
    
    @Binding var cameraPosition: MapCameraPosition
    @Binding var searchResults: [MKMapItem]
    @Binding var selectedResult: MKMapItem?
    @Binding var route: MKRoute?
    @Binding var visibleRegion: MKCoordinateRegion?
    @Binding var defaultSearchText: String
    @Binding var isLocationDeniedViewShown: Bool
    @Binding var isShowingBottomSheet: Bool
    @StateObject var locationManager = LocationManager()
    @StateObject var inAppPurchaseManager = InAppPurchaseManager()
    @EnvironmentObject var favoriteChargingPointSelection: FavoriteChargingPointSelection
    
    private let onboardingTip = OnboardingTip()
    
    var body: some View {
        NavigationStack {
            mapView
                .popoverTip(onboardingTip, arrowEdge: .top)
                .mapStyle(.standard(elevation: .realistic))
                .safeAreaInset(edge: .bottom) {
                    NavigationLink(destination: SettingsView(isShowingBottomSheet: $isShowingBottomSheet)) {
                        poiButtons
                            .background(.thinMaterial)
                    }
                }
                .sheet(isPresented: $isShowingBottomSheet) {
                    if let selectedResult {
                        ItemInfoView(
                            isShowingBottomSheet: $isShowingBottomSheet,
                            route: $route,
                            selectedTabBarButton: selectedTabBarButton,
                            selectedResult: selectedResult,
                            url: self.shareLocation()
                        )
                        .presentationDetents([.medium, .fraction(0.12), .large])
                        .presentationBackgroundInteraction(.enabled(upThrough: .medium))
                    }
                }
                .onAppear(perform: {
                    ReviewHandler.requestReview()
                })
                .onChange(of: searchResults) {
                    if !searchResults.isEmpty {
                        let results = searchResults.map { $0.placemark.coordinate }
                        visibleRegion = calculateRegionToFit(coordinates: results)
                        cameraPosition = .region(visibleRegion ?? MKCoordinateRegion())
                    }
                }
                .onChange(of: selectedResult) {
                    if let selectedResult {
                        getDirections()
                        if selectedResult.pointOfInterestCategory == .evCharger, let userLocation = locationManager.userLocation {
                            let region = MKCoordinateRegion(center: userLocation, span: MKCoordinateSpan(latitudeDelta: 0.0291, longitudeDelta: 0.060))
                            visibleRegion = region
                            cameraPosition = .region(visibleRegion ?? MKCoordinateRegion())
                            selectedTabBarButton = "EV"
                        } else {
                            if let userLocation = locationManager.userLocation {
                                let region = MKCoordinateRegion(center: userLocation, span: MKCoordinateSpan(latitudeDelta:0.0291, longitudeDelta: 0.060))
                                visibleRegion = region
                                cameraPosition = .region(visibleRegion ?? MKCoordinateRegion())
                                selectedTabBarButton = "Gas"
                            }
                        }
                    }
                }
                .onMapCameraChange { context in
                    visibleRegion = context.region
                }
                .mapControls {
                    MapUserLocationButton()
                    MapCompass()
                    MapScaleView()
                }
        }
    }
    
    var mapView: some View {
        Map(position: $cameraPosition, selection: $selectedResult) {
            ForEach(searchResults, id:\.self) {
                Marker(item: $0)
            }
            .annotationTitles(.hidden)
            
            UserAnnotation()
            
            if let route {
                MapPolyline(route)
                    .stroke(.blue, lineWidth: 5)
            }
        }
    }
    
    var poiButtons: some View {
        HStack {
            Spacer()
            VStack(spacing: 0) {
                POIButtons(
                    searchResults: $searchResults,
                    selectedTabBarButton: $selectedTabBarButton,
                    visibleRegion: $visibleRegion,
                    route: $route,
                    isShowingBottomSheet: $isShowingBottomSheet,
                    defaultSearchText: $defaultSearchText
                )
                .padding(.top)
            }
            Spacer()
        }
    }
}

extension LocationRequestIsOnView {
    func calculateRegionToFit(coordinates: [CLLocationCoordinate2D]) -> MKCoordinateRegion? {
        // First check if the coordinates array is empty
        guard !coordinates.isEmpty else {
            return nil
        }
        
        // Find the minimum and maximum latitude and longitude values of the search
        var minLat = coordinates[0].latitude
        var maxLat = coordinates[0].latitude
        var minLon = coordinates[0].longitude
        var maxLon = coordinates[0].longitude
        
        for coordinate in coordinates {
            minLat = min(minLat, coordinate.latitude)
            maxLat = max(maxLat, coordinate.latitude)
            minLon = min(minLon, coordinate.longitude)
            maxLon = max(maxLon, coordinate.longitude)
        }
        
        // Calculate the region based on the search values
        let center = CLLocationCoordinate2D(latitude: (minLat + maxLat) / 2, longitude: (minLon + maxLon) / 2)
        let latitudeDelta = maxLat - minLat
        let longitudeDelta = maxLon - minLon
        
        let paddingFactor = 1.2
        let span = MKCoordinateSpan(
            latitudeDelta: latitudeDelta * paddingFactor,
            longitudeDelta: longitudeDelta * paddingFactor
        )
        let region = MKCoordinateRegion(center: center, span: span)
        cameraPosition = .region(region)
        return region
    }
    
    func getDirections() {
        route = nil
        isShowingBottomSheet = true
        
        if let userLocation = locationManager.userLocation {
            let coordinate = userLocation
            let request = MKDirections.Request()
            
                request.source = MKMapItem(placemark: MKPlacemark(coordinate: coordinate))
                request.destination = selectedResult
                Task {
                    let directions = MKDirections(request: request)
                    let response = try? await directions.calculate()
                    route = response?.routes.first
                }
            }
        }
    
    func shareLocation() -> URL? {
        guard let sourceLatitude = locationManager.manager.location?.coordinate.latitude,
              let sourceLongitude = locationManager.manager.location?.coordinate.longitude,
              let destinationLatitude = selectedResult?.placemark.coordinate.latitude,
              let destinationLongitude = selectedResult?.placemark.coordinate.longitude
        else { return nil }
        
        let googleMapsInstalled = UIApplication.shared.canOpenURL(URL(string: "comgooglemaps://")!)
        
        if googleMapsInstalled {
            return URL(string: "comgooglemaps://?saddr=\(sourceLatitude),\(sourceLongitude)&daddr=\(destinationLatitude),\(destinationLongitude)&directionsmode=driving")
        } else {
            return URL(string: "https://maps.apple.com?saddr=\(sourceLatitude),\(sourceLongitude)&daddr=\(destinationLatitude),\(destinationLongitude)")
        }
    }
}

UIKit Internal bug: Unbalanced call to _endOcclusion, please file a feedback report with any information you have that helps reproduce this bug!
 
 
Q