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)") } } }