I have several problems with what should be an amazingly simple piece of code. The goal is to read items from a database and make them pins in a map. The pin should be a different color if the item has been flagged as a favorite.
The very first problem is that not all the items are being rendered. In the example I will use there are 12 results returned from the query and I have verified that each item gets an MKAnnotation created and each annotation gets a call to ViewFor.
In addition to not displaying all the pins there are two other problems.
First Pins randomly lose their title when scrolling the map.
Second The favorite (green tint) is seldom rendered green. 80% of the time it comes out in the standard blue. Once again I have verified that the MKMarkerAnnotationView color is set correctly.
With all these problems I am forced to conclude I am doing something fundamentally very wrong. Which is strange because this seems dead simple.
class FacilityMarker: NSObject, MKAnnotation {
// title and subtitle are from the MKAnnotation protocol
var coordinate: CLLocationCoordinate2D
var title: String?
var address: String
var phone: String
var providerNumber: String
var favorite: Bool
var subtitle: String? {
get {
return phone
}
}
View Controller
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
mapView.showAnnotations(mapView.annotations, animated: true)
// Create Annotations for all the facilities that are now visible on map
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let edgePoints = mapView.edgePoints()
let minLat = edgePoints.ne.latitude < edgePoints.sw.latitude ? edgePoints.ne.latitude : edgePoints.sw.latitude
let maxLat = edgePoints.ne.latitude > edgePoints.sw.latitude ? edgePoints.ne.latitude : edgePoints.sw.latitude
let minLong = edgePoints.ne.longitude < edgePoints.sw.longitude ? edgePoints.ne.longitude : edgePoints.sw.longitude
let maxLong = edgePoints.ne.longitude > edgePoints.sw.longitude ? edgePoints.ne.longitude : edgePoints.sw.longitude
let visibleCitiesReqeuest =
managedObjectModel.fetchRequestFromTemplate(withName: "FetchByCoordinates", substitutionVariables: ["minLat" : minLat, "minLong" : minLong, "maxLat" : maxLat, "maxLong" : maxLong])
do {
let facilities = try CoreDataHelper.shared.persistentContainer.viewContext.fetch(visibleCitiesReqeuest!) as! [FacilityMO]
for facility in facilities {
let facilityMarker = FacilityMarker(name: facility.facilityName!, address: facility.addressLine1!, location: facility.location!, phone: facility.phoneNumber!, providerNumber: facility.providerNumber!, favorite: facility.favorite)
mapView.addAnnotation(facilityMarker)
}
} catch {
let alertController = UIAlertController(title: "No Facilities", message: "There are no Facilities within the visible map area", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
}
// Put the pins in the map
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let annotation = annotation as? FacilityMarker else { return nil}
let identifier = "facility"
var view: MKMarkerAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as?
MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
print("CREATING NEW View for: \(annotation.title!)")
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}
// Set the Colors
if (annotation.favorite) {
view.markerTintColor = .green
view.tintColor = .green
} else {
view.markerTintColor = .blue
view.tintColor = .blue
}
return view
}
This is the actual data returned by the query. Only highlighted items are ever rendered. This is 100% consistent across all tests.
CREATING NEW View for: SEMINOLE DIALYSIS CENTER
CREATING NEW View for: RAI CARE CENTERS - LARGO
CREATING NEW View for: BAY BREEZE DIALYSIS CLINIC INC
CREATING NEW View for: FKC - BELLEAIR DIALYSIS CENTER
CREATING NEW View for: RAI CARE CENTERS - CLEARWATER
CREATING NEW View for: CORVA GULF COAST DIALYSIS CENTER
CREATING NEW View for: BMA - CLEARWATER
The following are captures showing the results described above
This is an initial render. This time the BMA pin is blue, it was set to Green.
After scrolling this time the BMA tint is correct. There is no pattern to when it will be right.
More scrolling and just to add more strangeness sometimes one or more annotations will not render their title attribute
The output from the requested debugging:
Try the following debug code. Can you show the output?
...
// Set the Colors
if (annotation.favorite) {
print(annotation.title, "is green")
view.markerTintColor = .green
view.tintColor = .green
} else {
print(annotation.title, "is blue")
view.markerTintColor = .blue
view.tintColor = .blue
}
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.