Swift performSegue going to Xcode - swift

I am trying to perform a Segue between two UI Views I have correctly typed the identifier for the segue as can be seen Here
This is my function, with the same identifier "no" but when the button is clicked in the simulator it simply shows This (It looks like it is showing the stack in bottom left?)
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "no", sender:self)
}
}
I have attached my full code incase further analysis is needed. Thanks for your help.
View Controller:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate,CLLocationManagerDelegate {
#IBOutlet weak var MapView: MKMapView!
let manager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//let location = locations[0]
//let span:MKCoordinateSpan = MKCoordinateSpanMake(0.02, 0.02)
//let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
}
override func viewDidLoad() {
super.viewDidLoad()
// tracking user's location
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// Setting up Map
let distanceSpan:CLLocationDegrees = 2000
MapView.setRegion(MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(-39.0556253, 174.0752278), distanceSpan, distanceSpan), animated: true)
MapView.showsUserLocation = true
MapView.delegate = self
// artwork on map
let windwandcoord: CLLocationCoordinate2D = CLLocationCoordinate2DMake(-39.055961,174.072288)
let artworkPin = Artwork(title:"Wind Wand",locationName:"Majestic",discipline:"Statue",
coordinate:windwandcoord)
MapView.addAnnotation(artworkPin)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation {return nil}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.calloutOffset = CGPoint(x: -5, y: 5)
let calloutButton = UIButton(type: .detailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}
return pinView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "no", sender:self)
}
}
}
Any help appreciated.

See the solid blue bar in the gutter in your screen shot?
It is a breakpoint. When the path of execution reaches a breakpoint that is active (solid blue like this), we pause there. That is what a breakpoint is for.
If you don't want that to happen, drag the breakpoint out of the gutter.

Related

Make mutliple pin annotations buttons to segue to an other view controller (swift 3)

I have two pin annotations on my map. I created a info button to perform the segue. But the button appears only on one annotation. Can anyone help me please? For the annotations I created a function that I put into the viewdidload method.
Here`s the code:
import UIKit
import MapKit
class MapVC: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
var locManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
meinkartenPunkt1()
meinkartenPunkt2()
locManager = CLLocationManager()
locManager.requestWhenInUseAuthorization()
// Do any additional setup after loading the view.
mapView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
func mapView(_ mapView: MKMapView,didUpdate userLocation: MKUserLocation){
mapView.region.center=userLocation.coordinate
mapView.showAnnotations(mapView.annotations, animated: true)
}
func meinkartenPunkt1() {
let breite: CLLocationDegrees = 8.737653
let länge: CLLocationDegrees = 47.504333
let Koordinaten = CLLocationCoordinate2DMake(länge, breite)
let Span = MKCoordinateSpanMake(0.01, 0.01)
let Region = MKCoordinateRegionMake(Koordinaten, Span)
mapView.setRegion(Region, animated: true)
let Stecknadel = MKPointAnnotation()
Stecknadel.coordinate = Koordinaten
Stecknadel.title = "Heiligberg"
mapView.addAnnotation(Stecknadel)
}
func meinkartenPunkt2() {
let breite: CLLocationDegrees = 8.734345
let länge: CLLocationDegrees = 47.508456
let Koordinaten = CLLocationCoordinate2DMake(länge, breite)
let Span = MKCoordinateSpanMake(0.01, 0.01)
let Region = MKCoordinateRegionMake(Koordinaten, Span)
mapView.setRegion(Region, animated: true)
let Stecknadel = MKPointAnnotation()
Stecknadel.coordinate = Koordinaten
Stecknadel.title = "Kanti Rychenberg"
mapView.addAnnotation(Stecknadel)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {return nil}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
let calloutButton = UIButton(type: .detailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}
return pinView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView,
calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "bookDetails", sender: self)
}
}
}
When looking at your source code, I cannot directly see an answer, however I see an immediate problem. You do some important setup on the pinView, while it is nil. To be honest, this code certainly crashes, if it is ever reached:
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
Luckily for you, pinView never is nil however, as the mapView creates the pinView successfully. What you probably want to do, is to set the calloutButton, if it is not set. So instead of if pinView == nil you write:
if pinView?.rightCalloutAccessoryView == nil {
// Initialize the rightCalloutAccessoryView here
}
Tip: In general you should avoid force unwraps with ! as it leads to crashes. Try to use optional chaining with ? instead.

swift, mapView, annotation view wont show upon tap

I implemented map view and created simple data model for annotations.
The pins are shown on the map, but I am still unable to get the details by tapping any pin.
My Code:
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var topView: MapDataView!
var dummyModel: DummyModel?
override func viewDidLoad() {
super.viewDidLoad()
dummyModel = DummyModel()
mapView.delegate = self
mapView.showsUserLocation = true
let region = MKCoordinateRegionMakeWithDistance(mapView.userLocation.coordinate, 1000, 1000)
mapView.setRegion(region, animated: true)
let range = 0..<Int((dummyModel?.objectsArray.count)!)
Array is valid and has no nil:
for i in range {
mapView.addAnnotation((dummyModel?.objectsArray[i])!)
}
The way i add annotation to the map:
mapView.selectAnnotation(mapView.annotations[0], animated: true)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
print("viewForAnnotation")
let identifier = "PubMapObject"
if annotation is PubMapObject {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView!.rightCalloutAccessoryView = btn
} else {
annotationView!.annotation = annotation
}
return annotationView
}
return nil
}
This method never called and i dont know why. i guess the problem is here, but i am unable to find it ):
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
print("annotationView")
let pub = view.annotation as! PubMapObject
}
}
Try to add set frame of annotation view before returning annotation view
//my annotation class and provide width and height to annotation view before returning the annotation view and give frame to
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation.isKind(of: MKUserLocation.self)) {
return nil
}
let reuseId = "PubMapObject"
if (annotation.isKind(of: PubMapObject.self)) {
let anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.isEnabled = true
anView.isUserInteractionEnabled = true
let btn = UIButton(type: .detailDisclosure)
btn.frame = CGRect(x: 0, y: 0, width: 50, height: 70)
anView!.rightCalloutAccessoryView = btn
anView.frame = CGRect(x: 0, y: 0, width: 50, height: 70)
return anView
}
return nil
}
Try using didSelect function instead of calloutAccessoryControlTapped.
func mapView(_ mapView: MKMapView, didSelect annotationView: MKAnnotationView) { ...

How To make Map Pins Animate drop? Swift 2.2 IOS 9

I have a basic setup here of a map in my view, I'm trying to make the pins animate a drop...Just like when you press & hold in the maps app and the pin drops to the location. So when I get in the view all the pins will animate a drop to their location and I really dont know how to do that . If anyone can guide me to the correct code I need to add that will be great!
Here is the Current Code I have :
class FirstViewController: UIViewController,MKMapViewDelegate, CLLocationManagerDelegate{
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
let LitzmanLocation = CLLocationCoordinate2DMake(32.100668,34.775192)
// Drop a pin
let Litzman = MKPointAnnotation()
Litzman.coordinate = LitzmanLocation
Litzman.title = "Litzman Bar"
Litzman.subtitle = "Nemal Tel Aviv St'"
mapView.addAnnotation(Litzman)}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of resources that can be re created.
}
//Mark:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
self.mapView.setRegion(region, animated: true)
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
print("Errors: " + error.localizedDescription)
}
Before all I am not maintaining any standards and I just have one of the solution for your problem and I am learning swift and mapKit by solving others problems.
Here I have given some sample code and I have added mapView and UITapGestureRecognizer through the Object library.
For adding annotation like dropping from top
pinView!.animatesDrop = true
in the viewForAnnotation delegation method.And addAnnotation method will call to add the annotation when you tap on the map.
For animating all the annotation
I have implemented regionDidChangeAnimated delegate method and just remove and add again all the annotations.
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
self.mapView.delegate = self
self.locationManager.delegate = self
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
let locationData = [
//Walker Art Gallery
["name": "Walker Art Gallery",
"latitude": 12,
"longitude": 79],
//Liver Buildings
["name": "Liver Buildings",
"latitude": 13,
"longitude": 77],
//St George's Hall
["name": "St George's Hall",
"latitude": 14,
"longitude": 77]
]
var annotations = [MKPointAnnotation]()
for each in locationData {
let latitude = CLLocationDegrees(each["latitude"] as! Double)
let longitude = CLLocationDegrees(each["longitude"] as! Double)
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let name = each["name"] as! String
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "\(name)"
annotations.append(annotation)
}
mapView.addAnnotations(annotations)
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
print("viewForAnnotation \(annotation.title)")
if annotation is MKUserLocation {
return nil
}
let reuseID = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseID) as? MKPinAnnotationView
if(pinView == nil) {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseID)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}
return pinView
}
#IBAction func addAnnotation(sender: UITapGestureRecognizer) {
if sender.state == .Ended {
let location = sender.locationInView(mapView)
let coordinate = mapView.convertPoint(location,toCoordinateFromView: mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
}
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
print("regionDidChangeAnimated")
let annotations = self.mapView.annotations
self.mapView.removeAnnotations(annotations)
self.mapView.addAnnotations(annotations)
}
}
EDIT
For your case in the viewDidLoad method add this
self.mapView.delegate = self
For annotating the MKAnnotation you have to implement the below delegate method
//Annotation view
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseID = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseID) as? MKPinAnnotationView
if(pinView == nil) {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseID)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}
return pinView
}
After for annotating all the annotation you have to implement below delegate method.
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let annotations = self.mapView.annotations
self.mapView.removeAnnotations(annotations)
self.mapView.addAnnotations(annotations)
}
And I am assuming you know how to add annotation on map tap...
EDIT2
Here is what you need my friend.
In the viewDidLoad add one notification observer as follows.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(didBecomeActive), name: UIApplicationDidBecomeActiveNotification, object: nil)
And lastly change that regionDidChangeAnimated to didBecomeActive as below
func didBecomeActive() {
let annotations = self.mapView.annotations
self.mapView.removeAnnotations(annotations)
self.mapView.addAnnotations(annotations)
}
In Objective C:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
// Try to dequeue an existing pin view first.
MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if (!pinView)
{
// If an existing pin view was not available, create one.
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
pinView.pinTintColor = [UIColor blueColor];
} else {
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}

MapKit in Swift, Part 2

I'm trying work with Map Kit in Swift. I try to display the area on the map, one pin (MKPinAnnotationView) and the current position. All display fine. I try to add Disclosure Button and intercept tapping on it. Disclosure Button added, but does not work intercept tapping.
Function pinPressed with method calloutAccessoryControlTapped not work....
This is a sample code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var mainMapView: MKMapView!
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
var objectLatitude = 53.204526
var objectLongitude = 50.111751
var currentLatitude = 53.203715
var currentLongitude = 50.160374
var latDelta = 0.05
var longDelta = 0.05
var currentLocationSpan: MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
var currentLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude, locationManager.location.coordinate.longitude)
var currentRegion: MKCoordinateRegion = MKCoordinateRegionMake(currentLocation, currentLocationSpan)
self.mainMapView.setRegion(currentRegion, animated: true)
var objectLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(objectLatitude, objectLongitude)
var objectAnnotation = MKPointAnnotation()
objectAnnotation.coordinate = objectLocation
objectAnnotation.title = "St. George's Church"
objectAnnotation.subtitle = "Church of the Great Martyr St. George"
self.mainMapView.addAnnotation(objectAnnotation)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Purple
pinView!.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as UIButton
}
else {
pinView!.annotation = annotation
}
return pinView
}
func pinPressed(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotationView.rightCalloutAccessoryView {
println("Disclosure Pressed!")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Just updating the calloutAccessoryControlTapped delegate method, because i try it today (09/06/2015) and not works. This input field changed: annotationView view: MKAnnotationView!
//Click on left or right button
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!)
{
let anotation = view.annotation as! MyAnnotation
if (control == view.rightCalloutAccessoryView)
{
println("Button right pressed!")
}
else if (control == view.leftCalloutAccessoryView)
{
println("Button left pressed!")
}
}
The calloutAccessoryControlTapped delegate method must be named mapView(annotationView:calloutAccessoryControlTapped:).
You can't use your own name like pinPressed(...).
This applies to any delegate method and is dictated by the protocol.
So it should be:
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotationView.rightCalloutAccessoryView {
println("Disclosure Pressed!")
}
}

How to disallow rotation on MKMapView but show heading?

For my project, I would like to put on a MKMapView the heading of the user without rotating the map (with the blue cone).
Here's a gist
Furthermore, with mapView.setUserTrackingMode(MKUserTrackingMode.FollowWithHeading, animated: true) enable, I can't navigate trough my map.
I tried to set the trackingMode on the mapView:didChangeUserTrackingMode but It's not working.
Any idea ?
I had the same issue and resolved it by using CLLocationManager and locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) method:
class MyViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView!
weak var userAnnotationView: MKAnnotationView?
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
mapView.showsUserLocation = true
mapView.delegate = self
locationManager.delegate = self
locationManager.startUpdatingHeading()
}
}
// MARK: - MKMapViewDelegate
extension MyViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? MKUserLocation {
// User
let reuseIdentifier = "UserAnnotationView"
let annotationView: MKAnnotationView
if let view = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) {
annotationView = view
} else {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
}
annotationView.image = UIImage(named: "userLocationWithoutHeading")
userAnnotationView = annotationView
return annotationView
} else {
return nil
}
}
}
// MARK: - CLLocationManagerDelegate
extension MyViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
guard let userAnnotationView = userAnnotationView else { return }
userAnnotationView.image = UIImage(named: "arrowUp")
let rotationAngle = heading.magneticHeading * Double.pi / 180.0
userAnnotationView.transform = CGAffineTransform(rotationAngle: CGFloat(rotationAngle))
}
}