When I press on a map pin, the detail view on a different View Controller for the selected restuarant’s pin is not shown. I think this is occurring because of the Task block I'm using.
Its an iOS application, with a minimum deployment of iOS 18.2.
I’m not using a do-catch block in this Task block.
Why is this happening? How do I fix this?
I think the didSelect mapView protocol function isn't being called because after the Task block runs, the rest of the code is not executed.
And I've tried placing that didSelect mapView protocol function, as well as the function for showing the detail view that is part of a different View Controller at the end of the Task block, and I used @MainActor for both functions, and it still didn't work.
I’ve included a simplified reproducible example below, and above this, just the function with the Task block. I've also included the print statements from the console when the minimum reproducible example is run.
Also the detail view just shows a generic text label right now when a map pin is selected.
Code:
Just the function with the Task block:
import UIKit
func startTaskOfGettingInitialMapVenueData() {
//Get venues data.
Task {
guard let mapVenues = try? await getMapVenues() else {return}
self.mapVenues = mapVenues
//Print Check.
print("Print Check. At the end of the Task block, and still within the Task block. mapVenues:", mapVenues)
self.showMapVenuesAsPins(mapVenues: self.mapVenues)
}
MapViewContoller.swift:
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
@IBOutlet var mapView: MKMapView!
var mapVenues: [InitialMapVenue] = []
//var mapVenues: [MapVenue] = []
override func viewDidLoad() {
super.viewDidLoad()
//centerOfRegion is Downtown San Francisco.
let centerOfRegion = CLLocationCoordinate2D(
latitude: 37.77531597108412, longitude: -122.42265827001113)
let region = MKCoordinateRegion(center: centerOfRegion, latitudinalMeters: 500, longitudinalMeters: 500)
mapView.setRegion(region, animated: true)
startTaskOfGettingInitialMapVenueData()
}
func startTaskOfGettingInitialMapVenueData() {
//Get venues data.
Task {
guard let mapVenues = try? await getMapVenues() else {return}
self.mapVenues = mapVenues
//Print Check.
print("Print Check. At the end of the Task block, and still within the Task block. mapVenues:", mapVenues)
self.showMapVenuesAsPins(mapVenues: self.mapVenues)
}
//Print Check.
print("Print Check. After the Task block, and right outside the Task block, and right before the for loop that shows each venue in venues as an annotation.")
}
func showMapVenuesAsPins(mapVenues: [InitialMapVenue]) {
//Print Check.
print("Print Check. Inside showMapVenuesAsPins function, and before the for loop.")
for element in mapVenues {
mapView.addAnnotation(element)
}
}
func getMapVenues() async throws -> [InitialMapVenue] {
let generatedMapVenues = [InitialMapVenue(name: "Rich Table", address: "199 Gough St, San Francisco, CA 94102", latitude: 37.774891876134795, longitude: -122.4227253023382, coordinate: CLLocationCoordinate2D(latitude: 37.774891876134795, longitude: -122.4227253023382)), InitialMapVenue(name: "The Bird", address: "406 Hayes St, San Francisco, CA 94102", latitude: 37.77696798656497, longitude: -122.42325276271241, coordinate: CLLocationCoordinate2D(latitude: 37.77696798656497, longitude: -122.42325276271241))]
return generatedMapVenues
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let restaurantPinAnnotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "MyMarker")
restaurantPinAnnotationView.markerTintColor = UIColor.blue
return restaurantPinAnnotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let mapVenue = view.annotation as? InitialMapVenue else { return }
presentDetailViewFromSelectedRestaurantPinFromMapModal(mapVenue: mapVenue)
}
private func presentDetailViewFromSelectedRestaurantPinFromMapModal(mapVenue: InitialMapVenue) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let detailViewForSelectedRestaurantFromMapVC = storyboard.instantiateViewController(identifier: "DetailViewForSelectedRestaurantFromMapViewController") as! DetailViewForSelectedRestaurantFromMapViewController
let nav = UINavigationController(rootViewController: detailViewForSelectedRestaurantFromMapVC)
nav.setNavigationBarHidden(true, animated: false)
nav.modalPresentationStyle = .pageSheet
if let sheet = nav.sheetPresentationController {
sheet.detents = [.medium(), .large()]
sheet.prefersGrabberVisible = true
}
detailViewForSelectedRestaurantFromMapVC.theMapVenue = mapVenue
present(nav, animated: true, completion: nil)
}
}
class InitialMapVenue: NSObject, MKAnnotation {
var name: String?
var address: String?
var latitude: Double?
var longitude: Double?
var coordinate: CLLocationCoordinate2D
var title: String? {
return name
}
init(name: String?,
address: String?,
latitude: Double?,
longitude: Double?,
coordinate: CLLocationCoordinate2D) {
self.name = name
self.address = address
self.latitude = latitude
self.longitude = longitude
self.coordinate = coordinate
}
}
DetailViewForSelectedRestaurantFromMapViewController.swift:
import UIKit
class DetailViewForSelectedRestaurantFromMapViewController: UIViewController {
var theMapVenue: InitialMapVenue!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Print Statements from the console:
*Log Statement saying a certain file is missing.*
Print Check. After the Task block, and right outside the Task block, and right before the for loop that shows each venue in venues as an annotation.
*Log Statement.*
Print Check. At the end of the Task block, and still within the Task block. mapVenues: [<V2_CodeNotExecutingAfterTaskBlock_MinimumReproducibleExample.InitialMapVenue: 0x60000261a1c0>, <V2_CodeNotExecutingAfterTaskBlock_MinimumReproducibleExample.InitialMapVenue: 0x6000026064c0>]
Print Check. Inside showMapVenuesAsPins function, and before the for loop.
Print Check. Inside showMapVenuesAsPins function, and after the for loop.
*Log Statement.*
*Log Statement.*
Task{...}.