How to customize default pin marker using Google Cluster Manager? - ios

How to customize default NOT CLUSTER, but red pin marker using Google Cluster Manager? There are some similar questions around but no working answer.
When I using:
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
marker.icon = UIImage(named: "my_marker")
marker.setIconSize(scaledToSize: .init(width: 18, height: 24))
}
It customizes clusters and icons too. How to customize pin marker only not cluster marker?

marker has a property iconView which is a UIView. Since it's a UIView you can customize however you want.
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
marker.iconView = MyView()
}

Works in Swift 5
class POIItem: NSObject, GMUClusterItem {
var position: CLLocationCoordinate2D
var name: String!
var icon: UIImage
init(position: CLLocationCoordinate2D, name: String, icon: UIImage) {
self.position = position
self.name = name
self.icon = icon
}
}
class PrincipalViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.google_map.clear()
let iconGenerator = GMUDefaultClusterIconGenerator()
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let renderer = GMUDefaultClusterRenderer(mapView: self.google_map, clusterIconGenerator: iconGenerator)
renderer.delegate = self
self.clusterManager = GMUClusterManager(map: self.google_map, algorithm: algorithm, renderer: renderer)
self.clusterManager.setDelegate(self, mapDelegate: self)
//insert your markers type POIItem
//self.clusterManager.add(item)
self.clusterManager.cluster()
}
}
extension PrincipalViewController: GMUClusterRendererDelegate {
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
if marker.userData is POIItem {
if let item = marker.userData as? POIItem {
marker.icon = item.icon
marker.title = item.name
}
}
if marker.userData is GMUStaticCluster {
if let staticCluster = marker.userData as? GMUStaticCluster {
//this is a custom UIView (.xib) contain a UIImage with custom marker and one label (countLabel) where show number of grouped markers
let customClusterMarker:CustomClusterMarker = CustomClusterMarker()
customClusterMarker.countLabel.text = "\(staticCluster.count)"
let view = UIView(frame: CGRect(x: 0, y: 0, width: 52, height: 70))
view.addSubview(customClusterMarker)
marker.iconView = view
}
}
}
}
extension PrincipalViewController: GMUClusterManagerDelegate {
func clusterManager(_ clusterManager: GMUClusterManager, didTap clusterItem: GMUClusterItem) -> Bool {
print("didTap clusterItem")
return true
}
func clusterManager(_ clusterManager: GMUClusterManager, didTap cluster: GMUCluster) -> Bool {
print("didTap cluster")
return true
}
}

Related

Xcode and iOS: debugQuickLookObject() showing MKMapView

In Xcode if you hover over a variable of type CLLocation and klick on the eye symbol, Xcode shows that location on a map.
To find bugs in data that is not mine, I wanted to have the same behaviour for objects of type MKPolyline.
First the test code:
import XCTest
import MapKit
class PolylineQuicklookTests: XCTestCase {
func testPolylineQuicklook() throws {
let wilhelma = CLLocationCoordinate2D(latitude: 48.804513, longitude: 9.206237)
let fernsehturm = CLLocationCoordinate2D(latitude: 48.755890, longitude: 9.190290)
let path = [wilhelma, fernsehturm]
let polyline = MKPolyline(coordinates: path, count: path.count)
print("set breakpoint here and test polyline Quicklook")
}
}
extend MKPolyline to invoke Quicklook:
extension MKPolyline {
#objc public func debugQuickLookObject() -> Any? {
//return "MKPolyline \(self.coordinates.count)"
quickLookMapVC = QuickLookMapVC(overlays: [self], annotations: [])
let view = quickLookMapVC?.view
return view
}
}
// hold reference:
fileprivate var quickLookMapVC: QuickLookMapVC?
And a simple implementation:
fileprivate class QuickLookMapVC: UIViewController {
var overlays: [MKOverlay] = []
var annotations: [MKAnnotation] = []
var mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
var testLabel = UILabel()
init() {
super.init(nibName: nil, bundle: nil)
}
convenience init(overlays: [MKOverlay], annotations: [MKAnnotation]) {
self.init()
print("QuickLookMapVC init \(overlays.count), \(annotations.count)")
self.overlays = overlays
self.annotations = annotations
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
print("QuickLookMapVC start viewDidLoad")
/*
testLabel.text = "Test"
testLabel.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(self.testLabel)
let constraints = [
testLabel.topAnchor.constraint(equalTo: view.topAnchor),
testLabel.leftAnchor.constraint(equalTo: view.leftAnchor),
view.bottomAnchor.constraint(equalTo: testLabel.bottomAnchor),
view.rightAnchor.constraint(equalTo: testLabel.rightAnchor)
]
NSLayoutConstraint.activate(constraints)
*/
mapView.delegate = self
mapView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(self.mapView)
let constraints = [
mapView.topAnchor.constraint(equalTo: view.topAnchor),
mapView.leftAnchor.constraint(equalTo: view.leftAnchor),
view.bottomAnchor.constraint(equalTo: mapView.bottomAnchor),
view.rightAnchor.constraint(equalTo: mapView.rightAnchor)
]
NSLayoutConstraint.activate(constraints)
mapView.mapType = .standard
mapView.addOverlays(overlays)
mapView.addAnnotations(annotations)
let stuttgart = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 48.775846, longitude: 9.182932),
latitudinalMeters: 5000, longitudinalMeters: 5000)
mapView.region = stuttgart
/*
if annotations.count > 0 {
mapView.showAnnotations(annotations, animated: true)
}
if let firstOverlay = overlays.first {
let mapRect = firstOverlay.boundingMapRect
print(mapRect)
mapView.visibleMapRect = mapRect
}
*/
}
}
extension QuickLookMapVC: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let polyline = overlay as? MKPolyline {
print("rendererFor polyline")
// for real applications do reuse instead of creating a new one each time:
let polylineRenderer = MKPolylineRenderer(polyline: polyline)
polylineRenderer.strokeColor = .red
// lineWith: defaults to 0, which is MKRoadWidthAtZoomScale(currentZoomScale)
return polylineRenderer
}
if let polygon = overlay as? MKPolygon {
print("rendererFor polygon")
let polygonrenderer = MKPolygonRenderer(polygon: polygon)
polygonrenderer.fillColor = .red
return polygonrenderer
}
print("rendererFor overlay")
return MKOverlayRenderer(overlay: overlay)
}
}
I'd expect so see at least a map.
What I'm seeing is an MKMapView with the usual Apple copyright symbols but no map.
The copyright symbols let me assume that the mapView is at least sized correctly and rendered.
Console shows
QuickLookMapVC init 1, 0
QuickLookMapVC start viewDidLoad
rendererFor polyline
When I replace MKMapView with a UILabel, the label is shown correctly.
This lets me assume that the invocation and the UIViewController parts work fine and only MKMapView is a problem.
What can I do that my code actually shows map data and a polyline?

How do you create a Custom Callout for Mapbox annotations?

I've tried for a few hours. The materials on the Mapbox Website just shows this:
func mapView(_ mapView: MGLMapView, calloutViewFor annotation: MGLAnnotation) -> MGLCalloutView? {
// Instantiate and return our custom callout view.
return CustomCalloutView(representedObject: annotation)
}
The problems are that there is no elaboration on what a 'CustomCalloutView' is or contains to achieve a CustomCallout. I understand (I think) its a class that implements MGLCalloutView but creating a class that correctly implements that method is no easy task, I am getting all sorts of errors particularly around one function 'self' -> Self.
It would be great to see an example of how to actually implement a Custom Callout. All of the conversations on Mapbox Git is just too complicated for a simpleton like me.
MGLAnnotation is a NSObjectProtocol, That only requires the classes and/or object that implements it to have a CLLocationCoordinate2D. This object should be your data model or relate very closely to it. For simplicity I inherited from NSObject.
CustomAnnotation.swift
import Foundation
import UIKit
import Mapbox
class CustomAnnotation: NSObject, MGLAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
var image: UIImage
init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String, image: UIImage) {
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
self.image = image
}
}
Your custom callout view (MGLCalloutView) is yet another protocol that any class or object inheriting from NSObject can conform to and has the following required properties, note that I am subclassing with UIView which inherits from NSObject:
class CustomCallOutView: UIView, MGLCalloutView {
var representedObject: MGLAnnotation
// Required views but unused for now, they can just relax
lazy var leftAccessoryView = UIView()
lazy var rightAccessoryView = UIView()
var delegate: MGLCalloutViewDelegate?
required init(annotation: MGLAnnotation) {
self.representedObject = annotation
super.init()
}
func presentCallout(from rect: CGRect, in view: UIView, constrainedTo constrainedRect: CGRect, animated: Bool) {
}
func dismissCallout(animated: Bool) {
}
}
Note that the require init(annotation:) is a bit misleading as one would expect annotation to be an object, instead it is an object that conforms to MGLAnnotation, so we can change this to our own data model version of MGLAnnotation.
required init(annotation: CustomAnnotation) {
self.representedObject = annotation
super.init()
}
Now, in the MGLCalloutViewDelegate delegate method presentCallout(rect:view:constrainedRect:) we add the custom callout (self) to the mapView which is passed into the delegate function as view. We also want to remove the view from the super view when it is dismissed:
func presentCallout(from rect: CGRect, in view: UIView, constrainedTo constrainedRect: CGRect, animated: Bool) {
view.addSubview(self)
}
func dismissCallout(animated: Bool) {
if (animated){
//do something cool
removeFromSuperview()
} else {
removeFromSuperview()
}
}
Finally in your mapView(_: calloutViewFor annotation:) method create a new custom annotation from your class or object that conformed to MGLAnnotation and pass it to your custom callout view:
func mapView(_ mapView: MGLMapView, calloutViewFor annotation: MGLAnnotation) -> MGLCalloutView? {
let title = annotation.title ?? nil
let subtitle = annotation.subtitle ?? nil
let image = UIImage(named: "apple.png")!
let customAnnotation = CustomAnnotation(coordinate: annotation.coordinate, title: title ?? "no title", subtitle: subtitle ?? "no subtitle", image: image)
return CustomCalloutView(annotation: customAnnotation)
}
For reference here is the rest of my full implementation:
CustomAnnotation.swift
see above
ViewController.swift
import UIKit
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate {
lazy var mapView: MGLMapView = {
let mv = MGLMapView(frame: self.view.bounds, styleURL: URL(string: "mapbox://styles/mapbox/streets-v10"))
mv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mv.setCenter(CLLocationCoordinate2D(latitude: 40.7326808, longitude: -73.9843407), zoomLevel: 9, animated: false)
return mv
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setup()
// Declare the marker `hello` and set its coordinates, title, and subtitle.
let hello = MGLPointAnnotation()
hello.coordinate = CLLocationCoordinate2D(latitude: 40.7326808, longitude: -73.9843407)
hello.title = "Hello world!"
hello.subtitle = "Welcome to my marker"
// Add marker `hello` to the map.
mapView.addAnnotation(hello)
}
func setup() {
self.view.addSubview(mapView)
mapView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Use the default marker. See also: our view annotation or custom marker examples.
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
return nil
}
// Allow callout view to appear when an annotation is tapped.
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
return true
}
func mapView(_ mapView: MGLMapView, calloutViewFor annotation: MGLAnnotation) -> MGLCalloutView? {
let title = annotation.title ?? nil
let subtitle = annotation.subtitle ?? nil
let image = UIImage(named: "apple.png")!
let customAnnotation = CustomAnnotation(coordinate: annotation.coordinate, title: title ?? "no title", subtitle: subtitle ?? "no subtitle", image: image)
return CustomCalloutView(annotation: customAnnotation)
}
}
CustomCalloutView
import Foundation
import Mapbox
class CustomCalloutView: UIView, MGLCalloutView {
var representedObject: MGLAnnotation
// Required views but unused for now, they can just relax
lazy var leftAccessoryView = UIView()
lazy var rightAccessoryView = UIView()
weak var delegate: MGLCalloutViewDelegate?
//MARK: Subviews -
let titleLabel:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.font = UIFont.boldSystemFont(ofSize: 17.0)
return label
}()
let subtitleLabel:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let imageView:UIImageView = {
let imageview = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
imageview.translatesAutoresizingMaskIntoConstraints = false
imageview.contentMode = .scaleAspectFit
return imageview
}()
required init(annotation: CustomAnnotation) {
self.representedObject = annotation
// init with 75% of width and 120px tall
super.init(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: UIScreen.main.bounds.width * 0.75, height: 120.0)))
self.titleLabel.text = self.representedObject.title ?? ""
self.subtitleLabel.text = self.representedObject.subtitle ?? ""
self.imageView.image = annotation.image
setup()
}
required init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup() {
// setup this view's properties
self.backgroundColor = UIColor.white
// And their Subviews
self.addSubview(titleLabel)
self.addSubview(subtitleLabel)
self.addSubview(imageView)
// Add Constraints to subviews
let spacing:CGFloat = 8.0
imageView.topAnchor.constraint(equalTo: self.topAnchor, constant: spacing).isActive = true
imageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: spacing).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 52.0).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 52.0).isActive = true
titleLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: spacing).isActive = true
titleLabel.leftAnchor.constraint(equalTo: self.imageView.rightAnchor, constant: spacing * 2).isActive = true
titleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -spacing).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
subtitleLabel.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: spacing).isActive = true
subtitleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: spacing).isActive = true
subtitleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -spacing).isActive = true
subtitleLabel.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
}
func presentCallout(from rect: CGRect, in view: UIView, constrainedTo constrainedRect: CGRect, animated: Bool) {
//Always, Slightly above center
self.center = view.center.applying(CGAffineTransform(translationX: 0, y: -self.frame.height))
view.addSubview(self)
}
func dismissCallout(animated: Bool) {
if (animated){
//do something cool
removeFromSuperview()
} else {
removeFromSuperview()
}
}
}

GMSMarker iconView weird behaviour when transform the marker

I am currently using Google Maps in an iOS application where I used iconView for the Marker when I tapped on the marker and scale the current selected marker other marker looks weird.
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool
{
if marker.userData != nil
{
let index : Int = Int(marker.userData as! String)!
//small all the marker
_ = markers.map { (marker) in
marker.iconView?.transform = CGAffineTransform.identity
}
markers[index].iconView?.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
setVenuePin(index: index)
}
return false
}

Swift: MapKit Custom Image Annotation

In my app, I have a mapkit and annotations with different colors. But, there are just three color options (red, green, purple). So, I need to change annotations with custom image.
I've followed this tutorial to create my mapview
Now, I have a Artwork class:
import Foundation
import MapKit
class Artwork: NSObject, MKAnnotation {
let title: String
let locationName: String
let color: String
let coordinate: CLLocationCoordinate2D
init(title: String, locationName: String, color: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.locationName = locationName
self.color = color
self.coordinate = coordinate
super.init()
}
var subtitle: String {
return locationName
}
// pinColor for disciplines: Sculpture, Plaque, Mural, Monument, other
func pinColor() -> MKPinAnnotationColor {
switch color {
case "Red":
return .Red
case "Purple":
return .Purple
case "Green":
return .Green
default:
return .Green
}
}
}
Also, VCMapView.swift file:
import Foundation
import MapKit
extension MapViewController: MKMapViewDelegate {
// 1
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if let annotation = annotation as? Artwork {
let identifier = "pin"
var view: MKPinAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
as? MKPinAnnotationView { // 2
dequeuedView.annotation = annotation
view = dequeuedView
} else {
// 3
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIView
}
view.pinColor = annotation.pinColor()
return view
}
return nil
}
}
And I can add pins on my map like this in viewdidload()
// show artwork on map
let artwork = Artwork(title: "\(self.plate)",
locationName: "\(self.location)",
color: "\(self.color)",
coordinate: CLLocationCoordinate2D(latitude: latitude, longitude: longtitude))
self.mapView.addAnnotation(artwork)
All work perfect but need to add custom image to this architecture, which part should I modify I am not sure.
In your architecture in my opinion, you should add an image property in the Artwork class and then use id in the .image property of MKPinAnnotationView.
ex:
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIView
}
view.image = UIImage(named:"your_image")
view.frame.size = CGSize(width: 30.0, height: 30.0) //not necessary but just to give you an idea how to resize just in case it is too large.

swift custom map class

I am learning Swift and want to create a subclass of MKMapKit to encapsulate some specific functionality, like checking distance between two points and creating custom annotations and separate all the map code into one class.
I have created a class:
class GameMapViewController: MKMapView, MKMapViewDelegate{...}
I initiate the class in code in the main view controller (and adding it as a subview to a view on the storyboard so I can control where it is more easily):
gameMap = GameMapViewController(container: mapViewHolder)
which sets everything up ok and all works EXCEPT for when I want to trigger a segue from a custom annotation:
func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKAnnotationView!) {...}
The didSelectAnnotationView gets called when I tap on an annotation callout but nothing has the method performSegueWithIdentifier that I am looking for, that all the solutions to similar questions suggest I should be using....
(I have tried putting a MapKit View onto the storyboard and changing its class to use GameMapViewController but none of the init functions get fired)
I am guessing its something to with how I am initialising my custom class?
MainViewController.swift:
override func viewDidLoad() {
super.viewDidLoad()
....
// Create the game map
gameMap = GameMapViewController(container: mapViewHolder)
mapViewHolder.addSubview(gameMap)
...
}
GameMapViewController.swift:
import UIKit
import MapKit
class GameMapViewController: MKMapView, MKMapViewDelegate{
var spanQuestion:MKCoordinateSpan = MKCoordinateSpanMake(180, 180)
var spanAnswer:MKCoordinateSpan = MKCoordinateSpanMake(180, 180)
var hasUserCityLocationGuess: Bool = false
var containingView: UIView
override init(){
println ("GameMapViewController init")
containingView = UIView()
super.init(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000))
self.delegate=self
var latDeltaAnswer:CLLocationDegrees = 50
var lngDeltaAnswer:CLLocationDegrees = 50
spanAnswer = MKCoordinateSpanMake(latDeltaAnswer, lngDeltaAnswer)
var latDeltaQuestion:CLLocationDegrees = 180
var lngDeltaQuestion:CLLocationDegrees = 180
spanQuestion = MKCoordinateSpanMake(latDeltaQuestion, lngDeltaQuestion)
}
required init(coder aDecoder: NSCoder) {
containingView = UIView()
super.init(coder: aDecoder)
self.delegate = nil
println ("GameMapViewController init with decoder")
}
convenience init(container: UIView) {
println ("GameMapViewController convenience")
self.init()
self.delegate = self
containingView = container
}
func mapViewDidFinishLoadingMap(mapView: MKMapView!) {
println("mapViewDidFinishLoadingMap")
}
func mapViewWillStartLoadingMap(mapView: MKMapView!) {
self.frame = CGRect (x: 0, y: 0, width: containingView.frame.width, height: containingView.frame.height)
self.contentMode = UIViewContentMode.ScaleAspectFill
superview?.sizeToFit()
var guessPlaceRecognizer = UILongPressGestureRecognizer(target: self, action: "guessPlace:")
guessPlaceRecognizer.minimumPressDuration = 1.0
mapView.addGestureRecognizer(guessPlaceRecognizer)
mapView.mapType = MKMapType.Satellite
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKCircle {
var circleRenderer = MKCircleRenderer(overlay: overlay)
circleRenderer.strokeColor = UIColor.redColor()
circleRenderer.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
circleRenderer.lineWidth = 1
//userOverlayCircleRender = circleRenderer
return circleRenderer
} else {
return nil
}
}
func guessPlace(gestureRecognizer:UIGestureRecognizer){
let guessPlaceFirst = NSUserDefaults.standardUserDefaults().boolForKey("guess_place_preference")
if guessPlaceFirst {
var touchPoint = gestureRecognizer.locationInView(self)
var newCoord:CLLocationCoordinate2D = self.convertPoint(touchPoint, toCoordinateFromView: self)
var userAnnotation = UserPointAnnotation()
userAnnotation.coordinate = newCoord
self.addAnnotation(userAnnotation)
var getLat: CLLocationDegrees = newCoord.latitude
var getLon: CLLocationDegrees = newCoord.longitude
var circleCenter: CLLocation = CLLocation(latitude: getLat, longitude: getLon)
addRadiusCircle(circleCenter)
hasUserCityLocationGuess = true
}
}
func showCity() {
let location = CLLocationCoordinate2D(latitude: (currentCity["latitude"]! as CLLocationDegrees), longitude: (currentCity["longitude"]! as CLLocationDegrees))
let region:MKCoordinateRegion = MKCoordinateRegionMake(location, self.spanAnswer)
let city: String = currentCity["city"]! as String
let conditions: String = currentCity["description"] as String
let country: String = currentCity["country"]! as String
let address = "\(city), \(country)"
let cityAnnotation = CityPointAnnotation()
cityAnnotation.title = address
cityAnnotation.subtitle = "\(conditions)"
cityAnnotation.coordinate = location
self.setRegion(region, animated: true)
self.addAnnotation(cityAnnotation)
self.selectAnnotation(cityAnnotation, animated: true)
}
func cityInfoClick(sender:UIButton){
//sender.performSegueWithIdentifier("segueCityWebView")
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
// Handle any custom annotations.
if annotation is CityPointAnnotation {
// Try to dequeue an existing pin view first.
let reuseId = "CityPointAnnotationView"
var annotationView = self.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
annotationView.image = UIImage(named: "marker.png")
annotationView.rightCalloutAccessoryView = UIButton.buttonWithType(.InfoDark) as UIButton
annotationView.canShowCallout = true
return annotationView;
} else {
annotationView.annotation = annotation
}
return annotationView
}
return nil;
}
func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKAnnotationView!) {
println("didSelectAnnotationView")
}
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
println("calloutAccessoryControlTapped1")
///////////////////
// I want to do a segue here
// but nothing has the method performSegueWithIdentifier (self, mapView, control....)
///////////////////
}
func resetMap(){
self.removeAnnotations(self.annotations)
self.removeOverlays(self.overlays)
var region:MKCoordinateRegion = MKCoordinateRegionMake(self.centerCoordinate, spanQuestion)
self.setRegion(region, animated: true)
hasUserCityLocationGuess = false
}
func addRadiusCircle(location: CLLocation){
var radius = NSUserDefaults.standardUserDefaults().doubleForKey("guess_place_radius") as CLLocationDistance
var circle = MKCircle(centerCoordinate: location.coordinate, radius: radius )
self.removeOverlays(self.overlays)
self.addOverlay(circle)
}
func doGeoCode( cityObject:PFObject ) -> Bool {
....
}
func userCityLocationGuess(userGuessTemp:Int)->NSDictionary {
....
}
}
It's because you're confusing views and view controllers. You have a view (subclass of MKMapView, but you're naming it and trying to use it as a controller. It is also doings the job of a controller.
So, you should really have a view controller which owns and configures a map view (plain MKMapView), and then it can interact with segues.

Resources