SWIFT 2: multiline MKPointAnnotation
Asked Answered
B

3

2

Is there a way to create multiline annotations?

Here is my code:

1) My customAnnotation class

import UIKit
import MapKit

class CustomAnnotation: NSObject, MKAnnotation {

    var title: String?
    var subtitle: String?
    var address: String = ""
    var phoneNumber: String = ""
    var workingHours: String = ""
    var coordinate: CLLocationCoordinate2D


    init(   title: String,
            subtitle: String,
            address: String,
            phoneNumber: String,
            workingHours: String,
            coordinate: CLLocationCoordinate2D ){

        self.title = title
        self.subtitle = subtitle
        self.address = address
        self.phoneNumber = phoneNumber
        self.workingHours = workingHours
        self.coordinate = coordinate

        super.init()
    }
}

2) my view controller with map:

class MapViewController: UIViewController, MKMapViewDelegate {

@IBOutlet weak var theMapView: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()


            let latitude: CLLocationDegrees = 54.685290
            let longitude : CLLocationDegrees = 25.279661

            let latDelta : CLLocationDegrees = 0.2
            let lonDelta : CLLocationDegrees = 0.2

            let theSpan : MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)

            let branchLocation : CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)

            let theRegion : MKCoordinateRegion = MKCoordinateRegionMake(branchLocation, theSpan)


            let annotation = CustomAnnotation(title: "Brach1", subtitle: "some text for B1", address: "address str 12-12", phoneNumber: "123 321 123", workingHours: "00 - 24", coordinate: branchLocation)


            self.theMapView.setRegion(theRegion, animated: true)

            self.theMapView.addAnnotation(annotation)

        }


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}


func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {

    let identifier = "MyPin"

    if annotation.isKindOfClass(MKUserLocation) {
        return nil
    }

    var annotationView: MKPinAnnotationView? = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView

    if annotationView == nil {

        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.canShowCallout = true

        let multiLineView = UIView(frame: CGRectMake(0, 0, 100, 40))

        let label1 = UILabel(frame: CGRectMake(0,0,100,20))
        label1.text = "Some text1"
        multiLineView.addSubview(label1)

        let label2 = UILabel(frame: CGRectMake(0,20,100,20))
        label2.text = "some text2"
        multiLineView.addSubview(label2)

        annotationView!.rightCalloutAccessoryView = multiLineView

    } else {
        annotationView!.annotation = annotation
    }
return annotationView
}

}

What I get:

enter image description here

If I would use

annotationView!.leftCalloutAccessoryView = multiLineView

I would get:

enter image description here

I haven't found any other methods. I would expect something like bottomCalouttAccessoryView to get something like:

enter image description here

That is very wired for me that the height of annotation is not amendable. (that is why my three lables don't even fit there) I was trying to play with autoresize methods of annotationview but with no luck:(

Bod answered 25/5, 2016 at 19:40 Comment(1)
are you check my code.Incombustible
R
1

The subtitle is a string that prints to a single line label, you would likely have to make a subclass in order to add multiple lines.

Rosary answered 25/5, 2016 at 19:43 Comment(1)
could you add more details on how to do it?Bod
C
1

have you looked at: How to display 2 lines of text for subtitle of MKAnnotation and change the image for the button on the right?

especially this part (I converted it to Swift for you)

   var multiLineView= UIView(frame: CGRectMake(0, 0, 23, 23))
    multiLineView.addSubview(lable1)
    multiLineView.addSubview(lable2)
    annotationView.leftCalloutAccessoryView = multiLineView

UPDATE

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView! {

var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin")

if pinView == nil {
    pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
    pinView!.canShowCallout = true

    // create a new View
    var multiLineView= UIView(frame: CGRectMake(0, 0, 23, 23))
    // add all the labels you need here
    let label1 = UILabel(frame: CGRectMake(0,10,10,10))
    label1.text = "Some text"
    multiLineView.addSubview(label1)
    let label2 = UILabel(frame: CGRectMake(0,20,10,10))
    label2.text = "some text"
    multiLineView.addSubview(label2)
    pinView!.leftCalloutAccessoryView = multiLineView


}
else {
    pinView!.annotation = annotation
}

return pinView

}

Calondra answered 25/5, 2016 at 22:4 Comment(16)
so if I declare labels like this: "let lable1 = UIView()" I can use them as argument in addSubview. but compiler still throws an error: "value of type MKPointAnnotation has no member 'leftCalloutAccessoryView' " What I am doing wrong? Not sure I understand well code in objective-c from your link.Bod
the annotationView must be of type MKAnnotationView, not MKPointAnnotation. for example: let annotationView = MKAnnotationView() . To create a lable you would declare the following: let label1 = UILabel(frame: CGRectMake(0,0,10,10). I'll edit my answer to clarify it.Calondra
When should I create this function and how it should be used? I will amend my question to add more clarity about my code. Maybe you could tell me where should I use your code than. thank youBod
It is a delegate method. You need to conform to the MKMapViewDelegate and then implement this method. It will be called once you add an annotation to the mapview. From your example, I can see that you are conforming to the protocol so all you have to do is add this method to your view controller. It will be called automatically once the self.theMapView.addAnnotation(annotation) is executed . Here is the link from the Apple Docs developer.apple.com/library/ios/documentation/MapKit/Reference/…Calondra
thank you. will try to collect all these pieces of puzzle into one picture:)Bod
you will have to tweak the values inside the CGRectMake to get the views to appear correctly. I just put some random values in there :)Calondra
Yes, sure. First i need to understand where it should be and after that adjust sizes of labelsBod
I marked your answer as useful cause it helped to add additional objects into annotation view. But I cant mark it as a correct answer. Question is updated for more details.Bod
have you tried subclassing MKAnnotationView? In the init method you can provide a custom Height and Width for the the bubble.Calondra
Rob88611 I am not very experienced in swift. I don't understand what do you mean by "subklassing MKAnnotatio"Bod
Do you know what subclassing means in programming? you basically extend the functionally of MKAnnotationView class to provide custom behavior that fits your needs. In swift you would do something like this class MyCustomMKAnnotationView : MKAnnotationView { ... } the apple documentation provide more details on how to subclass MKAnnotation. When I get home I can try it out and then post the code for you.Calondra
ROb8861 I know only theoretically what is that. Never tried it. I would appreciate if you could write how it should look like. thank youBod
Rob8861 any hope to hear from you?Bod
hi, sorry, I was very busy this weekend. Hopefully I can post the code today.Calondra
Hi! any news on our topic?Bod
@Bod plz check my answer.Incombustible
I
0

plz use this i programmatically set NSLayoutConstraint.

 func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {

        let identifier = "MyPin"

        if annotation.isKindOfClass(MKUserLocation) {
            return nil
        }

        var annotationView: MKPinAnnotationView? = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView

        if annotationView == nil {

            annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            annotationView?.canShowCallout = true

              let label1 = UILabel(frame: CGRectMake(0, 0, 200, 21))
            label1.text = "Some text1 some text2 some text2 some text2 some text2 some text2 some text2"
             label1.numberOfLines = 0
              annotationView!.detailCalloutAccessoryView = label1;

            let width = NSLayoutConstraint(item: label1, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.LessThanOrEqual, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200)
            label1.addConstraint(width)


            let height = NSLayoutConstraint(item: label1, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 90)
            label1.addConstraint(height)



        } else {
            annotationView!.annotation = annotation
        }
        return annotationView
    }


}

and output enter image description here

Incombustible answered 9/9, 2016 at 4:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.