Swift - 带图像的自定义MKPointAnnotation

时间:2017-02-20 17:57:57

标签: ios swift annotations mkmapview mapkit

我正在尝试创建要在地图视图中使用的自定义MKPointAnnotation。它看起来非常像Apple的照片中使用的那个:

enter image description here

我将从服务器检索大量照片及其位置。然后,我想显示一个类似上面的注释,注释中包含图像。

我目前有一个程序可以在正确的坐标处添加正常MKPointAnnotation,还可以从服务器检索相关照片。

我想要的只是将我的MKPointAnnotation设计成样式。

我尝试过其他答案,但我认为这有点不同,因为我想每次在模板上显示图像。

2 个答案:

答案 0 :(得分:14)

来自func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?

MKMapViewDelegate是您需要覆盖的功能。

它允许您为每个注释提供“自定义”视图。在此函数中,您可以将自定义视图(MKAnnotationView的子类)出列并设置自定义属性,也可以将具有属性MKAnnotationView的常规image出列。

您可以设置该属性以显示自定义图像。我宁愿使用我自己的annotationView,因为你可以添加自定义布局(标签,imageViews等)和主题(颜色,图层等)。

示例:

//
//  ViewController.swift
//  Maps
//
//  Created by Brandon T on 2017-02-20.
//  Copyright © 2017 XIO. All rights reserved.
//

import UIKit
import MapKit


class ImageAnnotation : NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?
    var image: UIImage?
    var colour: UIColor?

    override init() {
        self.coordinate = CLLocationCoordinate2D()
        self.title = nil
        self.subtitle = nil
        self.image = nil
        self.colour = UIColor.white
    }
}

class ImageAnnotationView: MKAnnotationView {
    private var imageView: UIImageView!

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

        self.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
        self.imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        self.addSubview(self.imageView)

        self.imageView.layer.cornerRadius = 5.0
        self.imageView.layer.masksToBounds = true
    }

    override var image: UIImage? {
        get {
            return self.imageView.image
        }

        set {
            self.imageView.image = newValue
        }
    }

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

class ViewController: UIViewController, MKMapViewDelegate {

    var mapView: MKMapView!
    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()


        self.initControls()
        self.doLayout()
        self.loadAnnotations()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func initControls() {
        self.mapView = MKMapView()

        self.mapView.isRotateEnabled = true
        self.mapView.showsUserLocation = true
        self.mapView.delegate = self

        let center = CLLocationCoordinate2DMake(43.761539, -79.411079)
        let region = MKCoordinateRegionMake(center, MKCoordinateSpanMake(0.005, 0.005))
        self.mapView.setRegion(region, animated: true)
    }

    func doLayout() {
        self.view.addSubview(self.mapView)
        self.mapView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.mapView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.mapView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.mapView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        self.mapView.translatesAutoresizingMaskIntoConstraints = false
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation.isKind(of: MKUserLocation.self) {  //Handle user location annotation..
            return nil  //Default is to let the system handle it.
        }

        if !annotation.isKind(of: ImageAnnotation.self) {  //Handle non-ImageAnnotations..
            var pinAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "DefaultPinView")
            if pinAnnotationView == nil {
                pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "DefaultPinView")
            }
            return pinAnnotationView
        }

        //Handle ImageAnnotations..
        var view: ImageAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: "imageAnnotation") as? ImageAnnotationView
        if view == nil {
            view = ImageAnnotationView(annotation: annotation, reuseIdentifier: "imageAnnotation")
        }

        let annotation = annotation as! ImageAnnotation
        view?.image = annotation.image
        view?.annotation = annotation

        return view
    }


    func loadAnnotations() {
        let request = NSMutableURLRequest(url: URL(string: "https://i.imgur.com/zIoAyCx.png")!)
        request.httpMethod = "GET"

        let session = URLSession(configuration: URLSessionConfiguration.default)
        let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
            if error == nil {

                let annotation = ImageAnnotation()
                annotation.coordinate = CLLocationCoordinate2DMake(43.761539, -79.411079)
                annotation.image = UIImage(data: data!, scale: UIScreen.main.scale)
                annotation.title = "Toronto"
                annotation.subtitle = "Yonge & Bloor"


                DispatchQueue.main.async {
                    self.mapView.addAnnotation(annotation)
                }
            }
        }

        dataTask.resume()
    }
}

答案 1 :(得分:2)

如果您想在地图中设置许多具有不同图片的位置,请使用以下代码:

@Brandon,谢谢

@objc func loadAnnotations() {

    for item in locations{
        DispatchQueue.main.async {
            let request = NSMutableURLRequest(url: URL(string: "<YourPictureUrl>")!)
            request.httpMethod = "GET"
            let session = URLSession(configuration: URLSessionConfiguration.default)
            let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
                if error == nil {

                    let annotation = ImageAnnotation()
                    annotation.coordinate = CLLocationCoordinate2DMake(Double(item["pl_lat"] as! String)!,
                                                                       Double(item["pl_long"] as! String)!)
                    annotation.image = UIImage(data: data!, scale: UIScreen.main.scale)
                    annotation.title = "T"
                    annotation.subtitle = ""
                    DispatchQueue.main.async {
                        self.mapView.addAnnotation(annotation)
                    }
                }
            }

            dataTask.resume()
        }
    }
}