Swift 如何自定义mkpin的图像

Swift 如何自定义mkpin的图像,swift,uikit,mkmapview,mkannotation,mkannotationview,Swift,Uikit,Mkmapview,Mkannotation,Mkannotationview,我正在尝试更改MKAnnotation中的图像,而不删除圆形 这里我创建了一个自定义类MKAnnotation: class MapPin: NSObject, MKAnnotation { let title: String? let locationName: String let coordinate: CLLocationCoordinate2D init(title: String, locationName: String, coordinate: C

我正在尝试更改
MKAnnotation
中的图像,而不删除圆形

这里我创建了一个自定义类
MKAnnotation

class MapPin: NSObject, MKAnnotation {
    let title: String?
    let locationName: String
    let coordinate: CLLocationCoordinate2D
    init(title: String, locationName: String, coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.locationName = locationName
        self.coordinate = coordinate
    }
}
在这里,我创建了一个MapPin,并将其添加到mapView中

func setPinUsingMKAnnotation() {
   let pin1 = MapPin(title: "Here", locationName: "Device Location", coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
   let coordinateRegion = MKCoordinateRegion(center: pin1.coordinate, latitudinalMeters: 800, longitudinalMeters: 800)
   mapView.setRegion(coordinateRegion, animated: true)
   mapView.addAnnotations([pin1])
}
第一个图像是我创建的,第二个图像是我想要的

我甚至实现了
MKMapViewDelegate

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    var annotationView = MKAnnotationView()
    annotationView.image = #imageLiteral(resourceName: "heart")
    return annotationView
}
结果是:

圆形消失了

我看过很多关于如何定制pin的教程,但它们只解释了如何放置图像而不是pin(如上面的壁炉图像)。我想知道如何更改针的图像(和颜色)并保持圆形(请参见上面的蓝色针图像)


有什么提示吗?谢谢

如果您想要圆形边框,您可以自己渲染,或者更简单地渲染,子类
mkmarkernotationview
而不是
MKAnnotationView

class CustomAnnotationView: MKMarkerAnnotationView {
    override var annotation: MKAnnotation? {
        didSet { configure(for: annotation) }
    }

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

        glyphImage = ...
        markerTintColor = ...
            
        configure(for: annotation)
    }

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

    func configure(for annotation: MKAnnotation?) {
        displayPriority = .required

        // if doing clustering, also add
        // clusteringIdentifier = ...
    }
}
这样,不仅可以获得圆形边框,还可以获得所有标记注释视图行为(显示标记下方注释视图的
标题
,如果在标记注释视图上选择,则它会变大,等等)。有很多标记注释视图行为,如果不需要的话,您可能不想从头开始编写。通过子类化
mkmarkernotationview
而不是普通的
MKAnnotationView
,您可以免费获得所有这些行为

例如,您可以:

class CustomAnnotationView: MKMarkerAnnotationView {
    static let glyphImage: UIImage = {
        let rect = CGRect(origin: .zero, size: CGSize(width: 40, height: 40))
        return UIGraphicsImageRenderer(bounds: rect).image { _ in
            let radius: CGFloat = 11
            let offset: CGFloat = 7
            let insetY: CGFloat = 5
            let center = CGPoint(x: rect.midX, y: rect.maxY - radius - insetY)
            let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: .pi, clockwise: true)
            path.addQuadCurve(to: CGPoint(x: rect.midX, y: rect.minY + insetY), controlPoint: CGPoint(x: rect.midX - radius, y: center.y - offset))
            path.addQuadCurve(to: CGPoint(x: rect.midX + radius, y: center.y), controlPoint: CGPoint(x: rect.midX + radius, y: center.y - offset))
            path.close()
            UIColor.white.setFill()
            path.fill()
        }
    }()

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

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

        glyphImage = Self.glyphImage
        markerTintColor = #colorLiteral(red: 0.005868499167, green: 0.5166643262, blue: 0.9889912009, alpha: 1)

        configure(for: annotation)
    }

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

    func configure(for annotation: MKAnnotation?) {
        displayPriority = .required

        // if doing clustering, also add
        // clusteringIdentifier = ...
    }
}
这将产生:

显然,当您设置
glyphmimage
时,请将其设置为所需的任何图像。旧的SF符号没有“drop”图像(尽管iOS 14有
drop.fill
)。但是提供您想要的任何40×40 pt图像视图。我自己绘制,但您可以使用资产目录(或系统符号)中任何适当大小的图像


另一方面,由于iOS 11,除非绝对必要(在本例中并非如此),否则您通常不会实现
mapView(uu2;:viewFor:)
。例如,您可以放弃
viewFor
方法,只需在
viewDidLoad
中注册自定义注释视图:

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

    ...
}

FWIW,我可能建议使用
MKPointAnnotation
而不是构建自己的
MKAnnotation
。或者,如果您确实需要一些附加属性,那么可以使用子类
MKPointAnnotation
,而不是从头开始。重新发明轮子没有意义(加上
MKPointAnnotation
使这些
title
coordinate
属性
dynamic
,这很有用)。