代码之家  ›  专栏  ›  技术社区  ›  mrkot

如何使用XIB创建自定义MKAnnotationView

  •  2
  • mrkot  · 技术社区  · 6 年前

    我想要一个自定义的MKAnnotationView。我在IB中创建了一个xib文件,并将其类设置为MyAnnotationView。

        class MyAnnotationView: MKAnnotationView {
    
        override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
            super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        @IBOutlet weak var textLabel: UILabel!
        @IBOutlet weak var busIcon: UIImageView!
    
    }
    

    以下是xib的外观-它有一个文本标签和一个busIcon链接:

    enter image description here

    viewFor annotation 用于为所有注释创建视图的委托方法:

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {     
    
            // Don't want to show a custom image if the annotation is the user's location.
            if (annotation is MKUserLocation) {
                return nil
            } else {
    
                let annotationIdentifier = "AnnotationIdentifier"
                var annotationView: MyAnnotationView?                           
    
    
                if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationIdentifier") as? MyAnnotationView {
                    annotationView = dequeuedAnnotationView
                    annotationView?.annotation = annotation
                } else {
    
                    // if no views to dequeue, create an Annotation View
                    let av = MyAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
                    av.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
                    annotationView = av     
                }
    
    
                if let annotationView = annotationView {
                    annotationView.canShowCallout = true                        // callout bubble
                    annotationView.image = UIImage(named: "Delivery")
                    annotationView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
                }
    
                return annotationView
    
            }
    
        }
    

    这个 annotationView.image = UIImage(named: "Delivery")

    &

    AnnotationView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
    

    我不知道该怎么做 方法使用我创建的XIB。谁能帮我一下吗?我搜索了解决方案,但只在Obj C中找到了相关的内容。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Shehata Gamal    6 年前

    1-创建的视图子类 UIView CallView

    viewforAnnotation

    let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "id") 
    let customView = Bundle.main.loadNibNamed("CallView", owner: self, options: nil).first! as! CallView
    // here configure label and imageView
    annotationView.addSubview(customView)
    
        2
  •  1
  •   mrkot    6 年前

    更新的代码基于 Sh-Khan's answer

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
                    //  Don't want to show a custom image if the annotation is the user's location.
                    if (annotation is MKUserLocation) {
                        return nil
                    } else {
    
                        let annotationIdentifier = "AnnotationIdentifier"
                        let nibName = "MyAnnotationView"
                        let viewFromNib = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! MyAnnotationView
                        var annotationView: MyAnnotationView?
    
                        // if there is a view to be dequeued, use it for the annotation
                        if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) as? MyAnnotationView {
    
                            if dequeuedAnnotationView.subviews.isEmpty {
                                dequeuedAnnotationView.addSubview(viewFromNib)
                            }
                            annotationView = dequeuedAnnotationView
                            annotationView?.annotation = annotation
                        } else {
    
                            // if no views to dequeue, create an Annotation View
                            let av = MyAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
                            av.addSubview(viewFromNib)
                            annotationView = av     // extend scope to be able to return at the end of the func
                        }
    
                        // after we manage to create or dequeue the av, configure it
                        if let annotationView = annotationView {
                            annotationView.canShowCallout = true                                    // callout bubble
                            annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
                            annotationView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
    
                            let customView = annotationView.subviews.first as! MyAnnotationView
                            customView.frame = annotationView.frame
                            customView.textLabel.text = (annotationView.annotation?.title)!
                        }
                        return annotationView
                    }
    }
    
        3
  •  0
  •   Kuldeep Singh    5 年前
    **Create Custom MKPointAnnotation Class**
    
    import UIKit
    import MapKit
    
        class CustomPointAnnotation: MKPointAnnotation {
           var id : Int
           var url : String
    
          init(id : Int , url : String ) {
          self.id = id
           self.url = url
    
    }
        }
    

    为注释视图的MarkerView类创建Xib

    class MarkerView: MKAnnotationView {
        @IBOutlet weak var imgVwUser: UIImageView!
    
    
    
         init(annotation: CustomPointAnnotation?, reuseIdentifier: String?) {
            super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
            let hitView = super.hitTest(point, with: event)
            if (hitView != nil)
            {
                self.superview?.bringSubviewToFront(self)
            }
            return hitView
        }
        override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            let rect = self.bounds
            var isInside: Bool = rect.contains(point)
            if(!isInside)
            {
                for view in self.subviews
                {
                    isInside = view.frame.contains(point)
                    if isInside
                    {
                        break
                    }
                }
            }
            return isInside
        }
    }
    

    extension YourViewController : MKMapViewDelegate {
    
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
            //  Don't want to show a custom image if the annotation is the user's location.
            if (annotation is MKUserLocation) {
                return nil
            } else {
    
                let annotationIdentifier = "AnnotationIdentifier"
                let nibName = "MarkerView"
                let viewFromNib = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! MarkerView
                var annotationView: MarkerView?
    
                // if there is a view to be dequeued, use it for the annotation
                if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) as? MarkerView {
    
                    if dequeuedAnnotationView.subviews.isEmpty {
                        dequeuedAnnotationView.addSubview(viewFromNib)
                    }
                    annotationView = dequeuedAnnotationView
                    annotationView?.annotation = annotation
                } else {
    
                    // if no views to dequeue, create an Annotation View
                    let av = MarkerView(annotation: annotation as? CustomPointAnnotation, reuseIdentifier: annotationIdentifier)
                    av.addSubview(viewFromNib)
                    annotationView = av     // extend scope to be able to return at the end of the func
                }
    
                // after we manage to create or dequeue the av, configure it
                if let annotationView = annotationView {
                    annotationView.canShowCallout = false                                    // callout bubble
    
    
                    if let annotation =  annotation as? CustomPointAnnotation {
    
    
                        annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
                        annotationView.frame = CGRect(x: 0, y: 0, width: 66, height: 75)
    
                        let customView = annotationView.subviews.first as? MarkerView
                        customView?.frame = annotationView.frame
                        let image = annotation.url
    
                        let imageUrl = URL(string: image)
    
    
                        customView?.imgVwUser.sd_setImage(with: imageUrl, placeholderImage:  UIImage(named:"defaults"), options: [.refreshCached], completed: nil)
    
    
                    }
                }
    
                return annotationView
            }
        }
    
    
    
    
         }
    

    将注释添加到地图视图

    extension YourViewController  {
    
        func addAnnotation(){
    
            let annotationsToRemove = mapView.annotations.filter { $0 !== mapView.userLocation }
            mapView.removeAnnotations( annotationsToRemove )
    
            var annotations: [CustomPointAnnotation] = []
    
            for  i in 0..<self.arrayData.count {
    
    
                let customPoints = CustomPointAnnotation.init(id: arrayData[i].id  ?? 0, url:  arrayData[i].url)
    
    
                let location = CLLocationCoordinate2DMake(self.arrayData[i].lat ?? 0, self.arrayData[i].lng ?? 0)
                customPoints.coordinate = location
    
                annotations.append(customPoints)
            }
    
            mapView.addAnnotations(annotations)
    
        }
    
    
    }