Home > Blockchain >  I have to add two pin annotation
I have to add two pin annotation

Time:03-26

I have to change image of my pin annotation in MapKit. And there should be two pin. One of these should be current location, second one is selector new location

func mapView(\_ mapView: MKMapView, viewFor annotation: MKAnnotation) -\> MKAnnotationView? {
    if annotation is MKUserLocation {
        return nil
    }

    let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customannotation")
    annotationView.image = UIImage(named:"pin")
    annotationView.canShowCallout = true
    return annotationView
}

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    print("annotation title == \(String(describing: view.annotation?.title!))")
}

CodePudding user response:

You said:

I have to change image of my pin annotation in MapKit.

If you are saying that you have an annotation showing its associated annotation view on the map, and you want to change the image for that annotation view, you can add a property to your annotation to indicate which image is to be shown, and then have a custom MKAnnotationView object which observes the annotation’s property and updates its image, accordingly.

For example, consider an annotation that has an imageName property:

class CustomAnnotation: MKPointAnnotation {
    @objc dynamic var imageName: String

    init(
        coordinate: CLLocationCoordinate2D,
        title: String? = nil,
        subtitle: String? = nil,
        imageName: String
    ) {
        self.imageName = imageName
        super.init()
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle
    }
}

Note, I made that an @objc dynamic property so that I can have an annotation view that observes that image name change:

class CustomAnnotationView: MKAnnotationView {
    static let reuseIdentifier = "CustomAnnotationView"

    override var annotation: MKAnnotation? {
        didSet { addObserver(for: annotation) }
    }

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        addObserver(for: annotation)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    var observer: NSKeyValueObservation?

    func addObserver(for annotation: MKAnnotation?) {
        let annotation = annotation as? CustomAnnotation
        let imageName = annotation?.imageName ?? "red"
        updateImage(named: imageName)

        observer = annotation?.observe(\.imageName) { [weak self] annotation, _ in
            self?.updateImage(named: annotation.imageName)
        }
    }

    private func updateImage(named name: String) {
        let image = UIImage(named: name)
        self.image = image

        // the following is only needed if you want the bottom of the
        // image over the coordinates (e.g., you are using a “pin”).

        if let image = image {
            centerOffset = CGPoint(x: 0, y: -image.size.height / 2)
        }
    }
}

So, you can create the annotation:

let annotation = CustomAnnotation(coordinate: coordinate, imageName: "red")
mapView.addAnnotation(annotation)

And when you want, you can update the imageName associated for that annotation, and the annotation view will observe that value change, and update the image accordingly:

annotation.imageName = "black"

That yields:

enter image description here


And there should be two pin. One of these should be current location, second one is selector new location

There is a special annotation for the user location, the MKUserLocation. Right now, your mapView(_:viewFor:) is returning nil for this annotation. Just change your viewFor to return whatever annotation you want for the MKUserLocation rather than nil.

Obviously this assumes (a) that you have enabled showsUserLocation property for your mapView and (b) that you have requested permission for the user’s location. E.g.:

private let manager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    if manager.authorizationStatus == .notDetermined {
        manager.requestWhenInUseAuthorization()
    }

    mapView.showsUserLocation = true
    ...
}

And of course, set the appropriate privacy strings in Info.plist:

enter image description here

CodePudding user response:

Once I had Faced the same issue... So I i used a for loop for this, In your case you can apply array for two pins or separate pin. Otherwise If you want to apply pins for multiple location at a same time than you do this by this logic.

Here's My code For Multiple pin

func showCurrentLocationOnMap(){
    for data in location
    {
        for address in data.address {
            let marker = GMSMarker()
            let markerLocation = CLLocationCoordinate2D(latitude: address.latitude, longitude: address.longitude)
                print("location: \(location)")
            let view = Bundle.main.loadNibNamed("Mapview", owner: self, options: nil)?.first as! Mapview
            let backImage = UIImage(named: "ic_map_pin")
            view.outerPinImage.image = backImage
            let urlString = data.business_logo.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
            view.innerPinImage.sd_setImage(with: URL(string: urlString!), completed: nil)
            print(view.innerPinImage!)
            marker.title = data.business_name
            marker.snippet = "View Details"
            marker.position = markerLocation
            marker.appearAnimation = GMSMarkerAnimation.pop
            DispatchQueue.main.async {
                view.innerPinImage.layer.cornerRadius = view.innerPinImage.frame.height/2
                marker.iconView = view
            }
            marker.map = mapView
            mapView.camera = GMSCameraPosition.camera(withLatitude: address.latitude, longitude: address.longitude, zoom: 15.0)
        } 
    }
}

You can Call this Function in Your View ForAnnotaion Mapview Method

  • Related