Could someone let me know why my labels are not being displayed. I am running a loop thru an array with coordinates in it. Its displaying my 3 pins with 1 being green, two blue which is what i want but my labels are not being displayed, any ideas?
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var maps: MKMapView!
var locationManager = CLLocationManager()
var flag = true
override func viewDidLoad() {
super.viewDidLoad()
let CoordinatesArray = ["blah,-blah, 11:45","blah, -blah,00:00", "blah,-blah, 12:45"];
self.maps.delegate = self
sendPoints(CoordinatesArray);
}
func sendPoints(array:[String]){
let latDelta:CLLocationDegrees = 0.015 //difference of lats from one side of screen to another
let longDelta:CLLocationDegrees = 0.015 //difference of lats from one side of screen to another
let span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
for (var i=0;i<array.count;i++){
var separateComma = array[i].componentsSeparatedByString(",")
var location:CLLocationCoordinate2D
if(flag){
location = CLLocationCoordinate2DMake(separateComma[0].doubleValue,separateComma[1].doubleValue)
let length:CLLocationDistance = 200
let cir:MKCircle = MKCircle(centerCoordinate: location, radius: length)
maps.addOverlay(cir)
}else{
location = CLLocationCoordinate2DMake(separateComma[0].doubleValue,separateComma[1].doubleValue)
}
let point = MKPointAnnotation()
point.title = "Home"
point.subtitle = "time for home"
point.coordinate = location
maps.addAnnotation(point)
maps.selectAnnotation(point, animated: true)
maps.setRegion(MKCoordinateRegionMake(point.coordinate, MKCoordinateSpanMake(latDelta,longDelta)), animated: true)
}
}
func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
let overlayRenderer : MKCircleRenderer = MKCircleRenderer(overlay: overlay);
overlayRenderer.lineWidth = 150
overlayRenderer.fillColor = UIColor.blueColor()
overlayRenderer.alpha = 0.15
return overlayRenderer
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation.isKindOfClass(MKUserLocation)){
return nil
}
var myPin = mapView.dequeueReusableAnnotationViewWithIdentifier("MyIdentifier") as? MKPinAnnotationView
if myPin != nil {
return myPin
}
myPin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "MyIdentifier")
if(flag){
myPin?.pinTintColor = UIColor.greenColor()
}else{
myPin?.pinTintColor = UIColor.blueColor()
}
flag = false;
return myPin
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}
You have to set canShowCallout property.
myPin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "MyIdentifier")
myPin?.canShowCallout = true
In my case I was delegating the map before being called.
So... that'd be the mistake I was facing.
self.m_map = MKMapView()
self.m_map?.delegate = self
Hope it helps somebody :-)
Related
I've tried to add title and subtitle to my annotations, but all my attempts had failed. Please help me!
import UIKit
import MapKit
class MyPointAnnotation : MKPointAnnotation{
var pinTintColor: UIColor?
}
class MapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self;
let hello = MyPointAnnotation()
hello.coordinate = CLLocationCoordinate2D(latitude: 46.771210, longitude: 23.623635)
hello.title = "tile"
hello.subtitle = "subtitle"
hello.pinTintColor = .blue
let hellox = MyPointAnnotation()
hellox.coordinate = CLLocationCoordinate2D(latitude: 44.426767, longitude: 26.102538)
hellox.pinTintColor = .blue
mapView.addAnnotation(hello)
mapView.addAnnotation(hellox)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
if #available(iOS 9.0, *) {
annotationView?.pinTintColor = annotation.pinTintColor
} else {
// Fallback on earlier versions
}
}
return annotationView
}
}
My problem solved with below code.In swift 4
#IBOutlet weak var map: MKMapView!
override func viewDidLoad() {
let location = CLLocationCoordinate2D(latitude: 12.956360, longitude: 77.716615)
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: 12.956360, longitude: 77.716615)
map.setRegion(MKCoordinateRegionMakeWithDistance(location, 1500, 1500), animated: true)
annotation.title = "your title"
annotation.subtitle = "your subtitle"
map.addAnnotation(annotation);
}
You need set canShowCallout true to show title and subtitle.
Try the following code.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
if #available(iOS 9.0, *) {
annotationView?.pinTintColor = annotation.pinTintColor
} else {
// Fallback on earlier versions
}
}
return annotationView
}
Im developing ipad app and looking memory using good all viewcontrollers but my MapDetailViewController gives me Received memory warning how can i resolve it .
All viewcontrollers use my app max 34.MB memory but MapDetailViewController using 100 MB More. My codes under below what is wrong ?
import UIKit
import MapKit
class MapDetailViewController: UIViewController,MKMapViewDelegate {
#IBOutlet var mapView:MKMapView!
#IBOutlet weak var mapArea: DesignableView!
#IBOutlet weak var nameSales: DesignableLabel!
var showmapListcomming = String()
override func viewDidLoad() {
super.viewDidLoad()
// Show Map
let myString: String = showmapListcomming
var myStringArr = myString.componentsSeparatedByString(",")
nameSales.text = myStringArr[0]
let annotation = MKPointAnnotation()
let latitude:CLLocationDegrees = (myStringArr[1] as NSString).doubleValue
let longitude:CLLocationDegrees = (myStringArr[2] as NSString).doubleValue
let latDelta:CLLocationDegrees = 150
let lonDelta:CLLocationDegrees = 150
let span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
let location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
mapView.setRegion(region, animated: false)
annotation.coordinate = location
annotation.title = myStringArr[0]
annotation.subtitle = "User"
mapView.addAnnotation(annotation)
}
// MARK: - MKMapViewDelegate methods
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKPinAnnotationView()
return annotationView
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I would have to add a button for my particular point of entry , where I click to open the Maps app already passing the coordinates of the selected point. Does anyone know how to do? my code is this. The image is what I would have.
My code:
import Foundation
import UIKit
import MapKit
import CoreLocation
class PuntiVenditaController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var menuButton:UIBarButtonItem!
#IBOutlet weak var mapView: MKMapView!
let regionRadius: CLLocationDistance = 1000
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
if revealViewController() != nil {
menuButton.target = revealViewController()
menuButton.action = "revealToggle:"
view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
let location = CLLocationCoordinate2D(latitude: 41.225891, longitude: 16.291489)
let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
mapView.setRegion(region, animated: true)
mapView.showsPointsOfInterest = false
mapView.showsUserLocation = true
displayMarkers()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
regionRadius * 2.0, regionRadius * 2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if control == view.rightCalloutAccessoryView{
println(view.annotation.title) // annotation's title
println(view.annotation.subtitle) // annotation's subttitle
//Perform a segue here to navigate to another viewcontroller
// On tapping the disclosure button you will get here
}
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("viewForannotation")
if annotation is MKUserLocation {
//return nil
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
//println("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}
var button = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as! UIButton // button with info sign in it
pinView?.rightCalloutAccessoryView = button
return pinView
}
func displayMarkers() -> Void
{
let annotationView = MKAnnotationView()
// Adding button here wont do anything so remove these two lines
let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as! UIButton
annotationView.rightCalloutAccessoryView = detailButton
// For adding button we have to use a method named as viewForAnnotation
let annotation = MKPointAnnotation()
let name = "Title"
let latitude = 41.225891
let longitude = 16.291489
annotation.title = name
var markerLatitude: Double = latitude
var markerLongitude: Double = longitude
let location = CLLocationCoordinate2D(latitude: markerLatitude, longitude: markerLongitude)
annotation.coordinate = location
annotation.subtitle = "Subtitle"
mapView.addAnnotation(annotation)
}
}
You can open an URL to open the Maps App at a specific point/address:
https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
But I don't think, you can design a custom marker within the Maps App
I am trying to create a custom Callout but for some reason the default point image does not change.
I am fetching the data for the points using Parse.
I have created a custom class (customAnnotationView) which inherits from MKAnnotationView and I am also overriding the mapView func.
The view controller is the following:
import UIKit
import Parse
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
#IBOutlet weak var map: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate=self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
var annotationQuery = PFQuery(className: "Doc")
annotationQuery.findObjectsInBackgroundWithBlock {
(Doc, error) -> Void in
if error == nil {
// The find succeeded.
print("Successful query for annotations")
let docs = Doc
for doctor in docs! {
let point = doctor["location"] as! PFGeoPoint
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(point.latitude, point.longitude)
annotation.title = String(doctor["name"])+String(doctor["surname"])
annotation.subtitle = String(doctor["address"])
print(doctor)
self.map.addAnnotation(annotation)
}
} else {
// Log details of the failure
print("Error: \(error)")
}
}
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var userLocation:CLLocation = locations[0]
var userLangtitude = userLocation.coordinate.latitude
var userLongtitude = userLocation.coordinate.longitude
// Initialize Map
var latidude:CLLocationDegrees = userLangtitude
var longtitude:CLLocationDegrees = userLongtitude
var latDelta:CLLocationDegrees = 2
var lonDelta:CLLocationDegrees = 2
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
var location: CLLocationCoordinate2D = CLLocationCoordinate2DMake(latidude,longtitude)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
self.map.setRegion(region, animated: true)
self.map.showsUserLocation = true;
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
// If annotation is user current location do not change the annotation
if annotation.isKindOfClass(MKUserLocation) {
return nil
}
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("customAnnotationView")
if annotationView == nil{
annotationView = customAnnotationView(annotation: annotation, reuseIdentifier: "customAnnotationView")
annotationView?.canShowCallout = true
}
else{
annotationView?.annotation = annotation
}
return annotationView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The customAnnotationView:
import UIKit
import MapKit
import CoreLocation
import Parse
class customAnnotationView: MKAnnotationView {
override init(frame: CGRect) {
super.init(frame: frame)
}
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
var frame = self.frame
frame.size = CGSizeMake(80,80)
self.frame = frame
self.backgroundColor = UIColor.clearColor()
self.centerOffset = CGPointMake(-5, -5)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
UIImage(named: "icon.png")?.drawInRect(CGRectMake(30,30, 30, 30))
}
}
Any help would be highly appreciated !
Thanks !
I managed to get a custom icon for a annotation pin in Swift, but now I am still stuck using 2 different images for different annotations. Right now a button adds a annotation to the map. There should be another button that also adds a annotation but with another icon.
Is there a way to use the reuseId for this?
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var Map: MKMapView!
#IBAction func btpressed(sender: AnyObject) {
var lat:CLLocationDegrees = 40.748708
var long:CLLocationDegrees = -73.985643
var latDelta:CLLocationDegrees = 0.01
var longDelta:CLLocationDegrees = 0.01
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat, long)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
Map.setRegion(region, animated: true)
var information = MKPointAnnotation()
information.coordinate = location
information.title = "Test Title!"
information.subtitle = "Subtitle"
Map.addAnnotation(information)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is MKPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.image = UIImage(named:"1.png")
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
return anView
}
In the viewForAnnotation delegate method, set the image based on which annotation the method is being called for.
Be sure to do this after the view is dequeued or created (and not only in the if anView == nil part). Otherwise, annotations that use a dequeued view will show the image of the annotation that used the view previously.
With the basic MKPointAnnotation, one crude way to tell annotations apart is by their title but that's not very flexible.
A better approach is to use a custom annotation class that implements the MKAnnotation protocol (an easy way to do that is to subclass MKPointAnnotation) and add whatever properties are needed to help implement the custom logic.
In the custom class, add a property, say imageName, which you can use to customize the image based on the annotation.
This example subclasses MKPointAnnotation:
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
}
Create annotations of type CustomPointAnnotation and set their imageName:
var info1 = CustomPointAnnotation()
info1.coordinate = CLLocationCoordinate2DMake(42, -84)
info1.title = "Info1"
info1.subtitle = "Subtitle"
info1.imageName = "1.png"
var info2 = CustomPointAnnotation()
info2.coordinate = CLLocationCoordinate2DMake(32, -95)
info2.title = "Info2"
info2.subtitle = "Subtitle"
info2.imageName = "2.png"
In viewForAnnotation, use the imageName property to set the view's image:
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as CustomPointAnnotation
anView.image = UIImage(named:cpa.imageName)
return anView
}
iOS Swift Code With Help of Anna and Fabian Boulegue:
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
var info1 = CustomPointAnnotation()
info1.coordinate = CLLocationCoordinate2DMake(26.889281, 75.836042)
info1.title = "Info1"
info1.subtitle = "Subtitle"
info1.imageName = "flag.png"
var info2 = CustomPointAnnotation()
info2.coordinate = CLLocationCoordinate2DMake(26.862280, 75.815098)
info2.title = "Info2"
info2.subtitle = "Subtitle"
info2.imageName = "flag.png"
mapView.addAnnotation(info1)
mapView.addAnnotation(info2)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
println("delegate called")
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as CustomPointAnnotation
anView.image = UIImage(named:cpa.imageName)
return anView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
}