I'm creating a tableViewCell with a mapView inside. however i can't seem to add a annotation based on a location in the viewController containing the tableView. i've started by in the cellForRowAtIndex by setting cell.location = orgObject.coordinate after that i've added following code to my custom cell. However location variable keep returning nil. i guess this is because awakeForNib is called before cellForRowAtIndexPath is called? how do i solve this?
import UIKit
import MapKit
class MapTableViewCell: UITableViewCell, MKMapViewDelegate {
var location: CLLocation?
#IBOutlet var mapView: MKMapView?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
//MapView
mapView!.showsPointsOfInterest = true
if let mapView = self.mapView
{
mapView.delegate = self
}
let orgLocation = CLLocationCoordinate2DMake(location!.coordinate.latitude, location!.coordinate.longitude)
let dropPin = MKPointAnnotation()
dropPin.coordinate = orgLocation
mapView!.addAnnotation(dropPin)
self.mapView?.setRegion(MKCoordinateRegionMakeWithDistance(orgLocation, 500, 500), animated: true)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialisation code
//MapView
mapView!.showsPointsOfInterest = true
if let mapView = self.mapView
{
mapView.delegate = self
}
}
Call cell.showLocation(location) from cellForRowAtIndexPath
func showLocation(location:CLLocation) {
let orgLocation = CLLocationCoordinate2DMake(location!.coordinate.latitude, location!.coordinate.longitude)
let dropPin = MKPointAnnotation()
dropPin.coordinate = orgLocation
mapView!.addAnnotation(dropPin)
self.mapView?.setRegion(MKCoordinateRegionMakeWithDistance(orgLocation, 500, 500), animated: true)
}
Related
So I have a MapView which adds a pin to the current user location. Also I have two textfields which displays the coordinates of the pin. I want to add two features:
When I drag and drop the pin, I want to update the coordinates inside the textfields.
When I edit the coordinates in the textfield, it should move the pin to the updated coorinates from the textfields.
Here my code where i handle everything for MapView. Im still pretty new to coding, so the code could be confusing, sorry for that.
class LocateVC: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var finishedLocateButton: UIButton!
#IBOutlet weak var relocateButton: UIButton!
var coordinates: [[Double]]!
var latTitleLabel:[String]!
var latValueLabel:[String]!
var lngTitleLabel:[String]!
var lngValueLabel: [String]!
var isEdited = false
var customCallout: UIView?
//Important to track location
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
view.layer.backgroundColor = Colors.grey.cgColor
//button titles
relocateButton.isHidden = true
relocateButton.setTitle("Relocate", for: .normal)
finishedLocateButton.setTitle("Continue", for: .normal)
navigationItem.title = "Location"
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
self.mapView.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
if isEdited == false {
if CLLocationManager.locationServicesEnabled() {
addPin()
}
}
// Latitude,Longitude
coordinates = [
[ProductData.shared.latitude!, ProductData.shared.longitude!],
]
} //end of viewDidLoad
override func viewWillAppear(_ animated: Bool) {
super.dismiss(animated: animated)
}
public func removePin() {
}
func dropPinFor(placemark: MKPlacemark) {
for annotation in mapView.annotations {
if annotation.isKind(of: MKPointAnnotation.self) {
// mapView.removeAnnotation(annotation) // removing the pins from the map
}
}
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
mapView.addAnnotation(annotation)
}
//1
public func addPin() {
if isEdited == false {
ProductData.shared.latitude = locationManager.location?.coordinate.latitude
ProductData.shared.longitude = locationManager.location?.coordinate.longitude
}
self.mapView.delegate = self
// adds an annotation to coordinates from productData
let point = ProductAnnotation(coordinate: CLLocationCoordinate2D(latitude: ProductData.shared.latitude! , longitude: ProductData.shared.longitude!))
self.mapView.addAnnotation(point)
// 3
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: ProductData.shared.latitude!, longitude: ProductData.shared.longitude!), span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
self.mapView.setRegion(region, animated: true)
}
public func editCoord() {
performSegue(withIdentifier: "editCoord", sender: CustomCalloutView.self)
}
#IBAction func relocateButtonClicked(_ sender: Any) {
addPin()
}
#IBAction func finishedLocateButtonClicked(_ sender: Any) {
performSegue(withIdentifier: "finishedLocateSegue2", sender: self)
}
//4
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
if view.isKind(of: CustomCalloutView.self ) || view.isKind(of: AnnotationView.self) || view.isKind(of: ProductAnnotation.self) {
return
} else {
customCallout?.removeFromSuperview()
}
}
//3
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if view.annotation is MKUserLocation {
return
}
//this creates the callout
let views = Bundle.main.loadNibNamed("CustomCalloutView", owner: nil, options: nil)
let calloutView = views?[0] as! CustomCalloutView
calloutView.delegate = self
calloutView.lngTitleLabel.text = "Lng"
calloutView.latTitleLabel.text = "Lat"
calloutView.lngTextField.text = String(format:"%f", ProductData.shared.longitude!)
calloutView.latTextField.text = String(format:"%f", ProductData.shared.latitude!)
calloutView.latTextField.layer.borderWidth = 0.0
calloutView.lngTextField.layer.borderWidth = 0.0
calloutView.latTextField.isEnabled = false
calloutView.lngTextField.isEnabled = false
calloutView.latTextField.keyboardType = .numberPad
calloutView.lngTextField.keyboardType = .numberPad
calloutView.alpha = 1.0
calloutView.layer.cornerRadius = 8
calloutView.center = CGPoint(x: view.bounds.size.width / 2, y: -calloutView.bounds.size.height*0.52)
customCallout = calloutView
view.addSubview(calloutView)
mapView.setCenter((view.annotation?.coordinate)!, animated: true)
}
//2
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil{
annotationView = AnnotationView(annotation: annotation, reuseIdentifier: "Pin")
annotationView?.isDraggable = true
annotationView?.canShowCallout = false
} else {
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "dot")
return annotationView
}
func saveButtonTapped() {
customCallout?.removeFromSuperview()
}
}
extension LocateVC: CustomCalloutViewDelegate {
func didClickEditButton() {
editCoord()
}
func didClickSaveButton() {
saveButtonTapped()
}
}
and here my custom callout:
class CustomCalloutView: UIView {
#IBOutlet weak var latTitleLabel: UILabel!
#IBOutlet weak var lngTitleLabel: UILabel!
#IBOutlet weak var editButton: UIButton!
#IBOutlet weak var saveButton: UIButton!
#IBOutlet weak var latTextField: UITextField!
#IBOutlet weak var lngTextField: UITextField!
var delegate: CustomCalloutViewDelegate?
var isEditing: Bool = false
#IBAction func didClickEditButton(_ sender: Any) {
// delegate?.didClickEditButton()
isEditing = true
latTextField.layer.borderWidth = 1.0
lngTextField.layer.borderWidth = 1.0
latTextField.isEnabled = true
lngTextField.isEnabled = true
saveButton.isHidden = false
}
#IBAction func saveButtonTapped(_ sender: Any) {
if isEditing == true {
if let lat = latTextField.text {
ProductData.shared.latitude = Double(lat)
}
if let lng = lngTextField.text {
ProductData.shared.longitude = Double(lng)
}
latTextField.layer.borderWidth = 0.0
lngTextField.layer.borderWidth = 0.0
latTextField.isEnabled = false
lngTextField.isEnabled = false
self.saveButton.setTitle("Save", for: .normal)
isEditing = false
} else {
self.saveButton.setTitle("Cancel", for: .normal)
delegate?.didClickSaveButton()
}
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if self.bounds.contains(point) {
return true
} else {
return self.subviews.contains { $0.frame.contains(point) }
}
}
}
protocol CustomCalloutViewDelegate {
func didClickEditButton()
func didClickSaveButton()
}
any idea how i can achive that? Maybe in a general way.
Thank you in advance
Here's a link to DSCenterPinMapView. A CocoaPod I recommend you to use.
It is a custom MapView with an animated and customizable center pin useful for selecting locations in map.
Here is also a guide on installing CocoaPods if it is new to you.
You should install the Pod an then, as a solution to your questions:
Implement the delegate so that you can get the location where pin drops.
pinMapView.delegate = self
extension MyViewController: DSCenterPinMapViewDelegate {
func didStartDragging() {
// My custom actions
}
func didEndDragging() {
// My custom actions
selectedLocation = pinMapView.mapview.centerCoordinate
// Update Text field
}
}
After you finish adding the coordinates on your TextFields you should call
pinMapView.center(on coordinate: myTextFieldCoordinate)
to center the map on the desired location.
After changing the marker position get coordinates like
let latitude = marker.coordinate.latitude
let longitude = marker.coordinate.longitude
And to set coordinate
let coordinate = CLLocationCoordinate2D(latitude: "your lat", longitude: "your long")
marker.coordinate = coordinate
mapView.setCenter(coordinate, animated: true)
if you not keeping the marker reference then
guard let marker = self.appleMap.annotations.first else {return}
let latitude = marker.coordinate.latitude
let longitude = marker.coordinate.longitude
And to set coordinate
guard let marker = self.appleMap.annotations.first else {return}
let coordinate = CLLocationCoordinate2D(latitude: "your lat", longitude: "your long")
marker.coordinate = coordinate
mapView.setCenter(coordinate, animated: true)
Hope that will help.
I'm currently trying to implement a Map connected with a search function. For the overlay containing the table view, I've decided to go for a library called FloatingPanel. Anyways, this shouldn't be of importance, since it shouldn't affect the essential code etc.
The data is being read inside of SearchResultsTableViewController and passed to MapViewController by passData().
Inside of passData() a function called addAnnotationToMap() from MapViewController is being called to process the data - printing inside of the function will always return the correct value.
Inside of the function I'm trying to add an annotation to the map, but it won't work. Nothing happens - but when I do print(mapView.annotations) the Array of annotations is being returned including mine.
By the way, I had to add loadViewIfNeeded() to the MapViewController because without (after using the overlay view) mapView returned nil.
Sorry for the amount of code - but there might be some relevant code. I didn't include the code for the table view.
MapViewController
class MapViewController: UIViewController, FloatingPanelControllerDelegate, UISearchBarDelegate {
var fpc: FloatingPanelController!
var searchVC = SearchResultTableViewController()
private enum AnnotationReuseID: String {
case pin
}
#IBOutlet private var mapView: MKMapView!
var mapItems: [MKMapItem]?
var boundingRegion: MKCoordinateRegion?
override func viewDidLoad() {
super.viewDidLoad()
if let region = boundingRegion {
mapView.region = region
}
fpc = FloatingPanelController()
fpc.delegate = self
// Initialize FloatingPanelController and add the view
fpc.surfaceView.backgroundColor = .clear
fpc.surfaceView.cornerRadius = 9.0
fpc.surfaceView.shadowHidden = false
searchVC = (storyboard?.instantiateViewController(withIdentifier: "SearchPanel") as! SearchResultTableViewController)
// Set a content view controller
fpc.set(contentViewController: searchVC)
fpc.track(scrollView: searchVC.tableView)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Add FloatingPanel to a view with animation.
fpc.addPanel(toParent: self, animated: true)
fpc.move(to: .tip, animated: true)
// Must be here
searchVC.searchController.searchBar.delegate = self
}
func addAnnotationToMap() {
loadViewIfNeeded()
guard let item = mapItems?.first else { return }
guard let coordinate = item.placemark.location?.coordinate else { return }
let annotation = MKPointAnnotation()
annotation.title = item.name
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.showsCancelButton = false
fpc.move(to: .tip, animated: true)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = true
searchVC.tableView.alpha = 1.0
fpc.move(to: .full, animated: true)
searchVC.hideHeader()
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
fpc.move(to: .half, animated: true)
searchVC.showHeader()
}
func floatingPanelDidMove(_ vc: FloatingPanelController) {
let y = vc.surfaceView.frame.origin.y
let tipY = vc.originYOfSurface(for: .tip)
if y > tipY - 44.0 {
let progress = max(0.0, min((tipY - y) / 44.0, 1.0))
self.searchVC.tableView.alpha = progress
}
}
func floatingPanelWillBeginDragging(_ vc: FloatingPanelController) {
if vc.position == .full {
searchVC.searchBar.showsCancelButton = false
searchVC.searchBar.resignFirstResponder()
}
}
func floatingPanelDidEndDragging(_ vc: FloatingPanelController, withVelocity velocity: CGPoint, targetPosition: FloatingPanelPosition) {
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: .allowUserInteraction,
animations: {
if targetPosition == .tip {
self.searchVC.tableView.alpha = 0.0
self.searchVC.hideHeader()
} else if targetPosition == .half {
self.searchVC.tableView.alpha = 1.0
self.searchVC.showHeader()
} else {
self.searchVC.tableView.alpha = 1.0
self.searchVC.hideHeader()
}
}, completion: nil)
}
}
SearchViewController
class SearchResultTableViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var visualEffectView: UIVisualEffectView!
private enum CellReuseID: String {
case resultCell
}
private var places: [MKMapItem]? {
didSet {
tableView.reloadData()
}
}
private var suggestionController: SuggestionsTableTableViewController!
var searchController: UISearchController!
private var localSearch: MKLocalSearch? {
willSet {
places = nil
localSearch?.cancel()
}
}
private var boundingRegion: MKCoordinateRegion?
override func awakeFromNib() {
super.awakeFromNib()
suggestionController = SuggestionsTableTableViewController()
suggestionController.tableView.delegate = self
searchController = UISearchController(searchResultsController: suggestionController)
searchController.searchResultsUpdater = suggestionController
searchController.searchBar.isUserInteractionEnabled = false
searchController.searchBar.alpha = 0.5
}
override func viewDidLoad() {
super.viewDidLoad()
searchBar.addSubview(searchController.searchBar)
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.tintColor = .black
searchController.searchBar.isUserInteractionEnabled = true
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
hideHeader()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 10, *) {
visualEffectView.layer.cornerRadius = 9.0
visualEffectView.clipsToBounds = true
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func showHeader() {
changeHeader(height: 116.0)
}
func hideHeader() {
changeHeader(height: 0.0)
}
func changeHeader(height: CGFloat) {
tableView.beginUpdates()
if let headerView = tableView.tableHeaderView {
UIView.animate(withDuration: 0.25) {
var frame = headerView.frame
frame.size.height = height
self.tableView.tableHeaderView?.frame = frame
}
}
tableView.endUpdates()
}
func passData() {
guard let mapViewController = storyboard?.instantiateViewController(withIdentifier: "map") as? MapViewController else { return }
guard let mapItem = places?.first else { return }
guard let coordinate = mapItem.placemark.location?.coordinate else { return }
let span = MKCoordinateSpan(latitudeDelta: coordinate.latitude, longitudeDelta: coordinate.longitude)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapViewController.boundingRegion = region
mapViewController.mapItems = [mapItem]
mapViewController.addAnnotationToMap()
}
private func search(for suggestedCompletion: MKLocalSearchCompletion) {
let searchRequest = MKLocalSearch.Request(completion: suggestedCompletion)
search(using: searchRequest)
}
private func search(for queryString: String?) {
let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = queryString
search(using: searchRequest)
}
private func search(using searchRequest: MKLocalSearch.Request) {
if let region = boundingRegion {
searchRequest.region = region
}
UIApplication.shared.isNetworkActivityIndicatorVisible = true
localSearch = MKLocalSearch(request: searchRequest)
localSearch?.start { [weak self] (response, error) in
if error == nil {
self?.passData()
} else {
self?.displaySearchError(error)
return
}
self?.places = response?.mapItems
self?.boundingRegion = response?.boundingRegion
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
private func displaySearchError(_ error: Error?) {
if let error = error as NSError?, let errorString = error.userInfo[NSLocalizedDescriptionKey] as? String {
let alertController = UIAlertController(title: "Could not find any places.", message: errorString, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController, animated: true, completion: nil)
}
}
}
I can't figure out why the table view controller is not populating with placeMarks.name and coordinates. The user taps a pin on the map and adds the location to the model. Where then it sent to the table view controller, however, it is not displaying the data from the model. Below is my code.
import Foundation
import CoreLocation
class PlaceList : NSObject {
let locations: Places
var coordinate: CLLocationCoordinate2D { return locations.coordinate }
init(point: Places) {
self.locations = point
super.init()
}
var title: String? {
return locations.name
}
var subtitle: String? {
return "(\(locations.coordinate.latitude), \(locations.coordinate.longitude))"
}
}
import CoreLocation
import Foundation
class Places: NSObject {
var name: String
var coordinate: CLLocationCoordinate2D
init(name: String, coordinate: CLLocationCoordinate2D) {
self.name = name
self.coordinate = coordinate
}
}
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate,CLLocationManagerDelegate {
var placeModel: PlaceList?
var pointOfInterest: [Places] = []
var poi: [Places] = [] {
didSet {
pointOfInterest = poi
}
}
//Creating mapview object
var mapView: MKMapView!
var geoCoder = CLGeocoder()
//Initial cooridinate
var latitude = 43.136581
var longitude = -87.941101
var latitudeDelta = 0.3
var longitudeDelta = 0.3
//the object that determines the location
let placeManger = CLLocationManager()
//loading the map on the scene
override func loadView() {
super.loadView()
mapView = MKMapView()
view = mapView
placeManger.startUpdatingLocation()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
navigationItem.title = "Travel Wishlist"
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.barTintColor = .blue
placeManger.delegate = self
placeManger.requestWhenInUseAuthorization()
mapView.delegate = self
navigationItem.rightBarButtonItem = rightBar
navigationItem.leftBarButtonItem = leftBar
mapView.addGestureRecognizer(tapGestrueRecongnizer)
centerMapInInitialCoordinates()
showPointsOfInterestInMap()
}
func showPointsOfInterestInMap() {
mapView.removeAnnotations(mapView.annotations)
for point in poi {
let pin = PlaceList(point: point)
mapView.addAnnotation(pin as! MKAnnotation)
}
}
func centerMapInInitialCoordinates() {
let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta)
let region:MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), span: span)
mapView.setRegion(region, animated: true)
}
var tapGestrueRecongnizer: UITapGestureRecognizer {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(loadPointOfInterests(recongnizer:)))
return tapGesture
}
var rightBar: UIBarButtonItem {
let rightBarButton =
UIBarButtonItem(title: "Find a place to add",
style: .plain, target: self,
action: #selector(rightbarButton))
rightBarButton.tintColor = .white
return rightBarButton
}
var leftBar: UIBarButtonItem {
let leftBarButton =
UIBarButtonItem(title:
"Look up", style: .plain,
target: self, action: #selector(leftButton))
leftBarButton.tintColor = .white
return leftBarButton
}
#objc func leftButton(leftButton: UIBarButtonItem) {
print("Left BarButton")
performSegue(withIdentifier: "place", sender: leftButton)
addPlace()
}
#objc func rightbarButton(right: UIBarButtonItem) {
addPlace()
}
func addPlace(){
// mapView.removeAnnotations(mapView.annotations)
for point in pointOfInterest {
let pin = PlaceList(point: point)
mapView.addAnnotation(pin as! MKAnnotation)
}
filterVisiblePOI()
}
func filterVisiblePOI() {
let visibleAnnotations = self.mapView.annotations(in: self.mapView.visibleMapRect)
var annotations = [PlaceList]()
for visibleAnnotation in visibleAnnotations {
if let annotation = visibleAnnotation as? PlaceList {
annotations.append(annotation)
}
}
}
#objc func loadPointOfInterests(recongnizer:UITapGestureRecognizer) {
let locationPoint = recongnizer.location(in: mapView)
let cooridinate = mapView.convert(locationPoint, toCoordinateFrom: mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = cooridinate
mapView.addAnnotation(annotation)
geoCoder.reverseGeocodeLocation(CLLocation(latitude: cooridinate.latitude, longitude: cooridinate.longitude)) {(placeMarks : [CLPlacemark]?, error: Error?) in
if let placeLocation = placeMarks?[0] {
if error == nil && (placeMarks?.count)! > 0 {
let locationString = " \(placeLocation.name!)"
annotation.coordinate = cooridinate
annotation.title = locationString
print(locationString)
}
for point in self.pointOfInterest {
let pin = PlaceList(point: point)
self.mapView.addAnnotation(pin as! MKAnnotation)
self.poi.append(point)
print(point)
print(self.pointOfInterest)
print(pin)
}
}
}
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
self.navigationItem.rightBarButtonItem?.title = "Find a place to add"
}
private func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
//To Do
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "place" {
let nav = segue.destination as! UINavigationController
let detailViewControll = nav.topViewController as! VisitationTableViewController
for point in pointOfInterest {
let pin = PlaceList(point: point)
mapView.addAnnotation(pin as! MKAnnotation)
detailViewControll.poi = pointOfInterest
}
}
}
}
import Foundation
import UIKit
class VisitationTableViewController: UITableViewController {
var poi: [Places] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
let dissButton = UIBarButtonItem(title: "Done", style: .done
, target: self, action: #selector(dismisController))
self.navigationItem.rightBarButtonItem = dissButton
dissButton.tintColor = .white
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Visited"
navigationController?.navigationBar.barTintColor = .blue
print("view didload")
print(poi)
}
#objc func dismisController() {
presentingViewController?.dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return poi.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath)
let point = poi[indexPath.row]
cell.textLabel?.text = point.name
cell.detailTextLabel?.text = "(\(point.coordinate.latitude), \(point.coordinate.longitude))"
return cell
}
}
You may need
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
self.performSegue(withIdentifier:"place",sender:nil)
}
And make sure segue source is connected to the vc itself ( drag it from yellow roundec icon of mapVC inside IB )
When I ran the code, tapping into the map didn't add any object to pointOfInterest, which you are making a loop on loadPointOfInterests to add an object to poi but its empty, so make sure to add a Place object in poi
In VisitationTableViewController, make sure to add
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "locationCell")
}
I am using a search bar to use Google Place Autocomplete feature. However, it is not working when I am putting the search bar on top of GMSMapView. It works completely fine when I comment out loadView() function. Is there a way to use the place autocomplete with Google map?
import UIKit
import GoogleMaps
class ViewController: UIViewController {
var resultsViewController: GMSAutocompleteResultsViewController?
var searchController: UISearchController?
var resultView: UITextView?
override func loadView() {
let camera = GMSCameraPosition.cameraWithLatitude(1.285, longitude: 103.848, zoom: 12)
let mapView = GMSMapView.mapWithFrame(.zero, camera: camera)
self.view = mapView
}
override func viewDidLoad() {
super.viewDidLoad()
resultsViewController = GMSAutocompleteResultsViewController()
resultsViewController?.delegate = self
searchController = UISearchController(searchResultsController: resultsViewController)
searchController?.searchResultsUpdater = resultsViewController
let subView = UIView(frame: CGRectMake(0, 65.0, 350.0, 45.0))
subView.addSubview((searchController?.searchBar)!)
self.view.addSubview(subView)
searchController?.searchBar.sizeToFit()
searchController?.hidesNavigationBarDuringPresentation = false
// When UISearchController presents the results view, present it in
// this view controller, not one further up the chain.
self.definesPresentationContext = true
}
}
// Handle the user's selection.
extension ViewController: GMSAutocompleteResultsViewControllerDelegate {
func resultsController(resultsController: GMSAutocompleteResultsViewController,
didAutocompleteWithPlace place: GMSPlace) {
searchController?.active = false
// Do something with the selected place.
print("Place name: ", place.name)
print("Place address: ", place.formattedAddress)
print("Place attributions: ", place.attributions)
}
func resultsController(resultsController: GMSAutocompleteResultsViewController,
didFailAutocompleteWithError error: NSError){
// TODO: handle the error.
print("Error: ", error.description)
}
// Turn the network activity indicator on and off again.
func didRequestAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController) {
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
}
The code above is from https://developers.google.com/maps/documentation/ios-sdk/map and https://developers.google.com/places/ios-api/autocomplete. I copied these for testing and is still not working.
Sorry, I don't have the reputation to write comments yet, but I think this could help you to figure out the issue.
First call the super.loadView() and when you initialize the GMSMapView you must set a frame size. Finally add the mapView to the subview.
override func loadView() {
super.loadView()
let camera = GMSCameraPosition.cameraWithLatitude(1.285, longitude: 103.848, zoom: 12)
let mapView = GMSMapView.mapWithFrame(self.view.frame, camera: camera)
self.view.addSubview(mapView)
}
Please help me with this problem
import Foundation
import UIKit
import MapKit
class DetailViewController : UIViewController {
#IBOutlet weak var mapView: MKMapView!
var selectedLocation : LocationModel?
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
// Create coordinates from location lat/long
var poiCoodinates: CLLocationCoordinate2D = CLLocationCoordinate2D()
poiCoodinates.latitude = CDouble(self.selectedLocation!.latitude!)! //Problem is in this line
poiCoodinates.longitude = CDouble(self.selectedLocation!.longitude!)!
// Zoom to region
let viewRegion: MKCoordinateRegion = MKCoordinateRegionMakeWithDistance(poiCoodinates, 750, 750)
self.mapView.setRegion(viewRegion, animated: true)
// Plot pin
let pin: MKPointAnnotation = MKPointAnnotation()
pin.coordinate = poiCoodinates
self.mapView.addAnnotation(pin)
//add title to the pin
pin.title = selectedLocation!.name
}
}
You have not initialised var selectedLocation : LocationModel? so when you ask for self.selectedLocation! it crash.
Add that needed initialisation and try to refactor your code in this
way:
override func viewDidAppear(animated: Bool) {
guard let location = self.selectedLocation, let latitude = location.latitude, let longitude = location.longitude else {
return //Here was an error, so you can not continue, report it or do something about it before returning
}
// Create coordinates from location lat/long
var poiCoodinates: CLLocationCoordinate2D = CLLocationCoordinate2D()
poiCoodinates.latitude = CDouble(latitude)!
poiCoodinates.longitude = CDouble(longitude)!
// Zoom to region
let viewRegion: MKCoordinateRegion = MKCoordinateRegionMakeWithDistance(poiCoodinates, 750, 750)
self.mapView.setRegion(viewRegion, animated: true)
// Plot pin
let pin: MKPointAnnotation = MKPointAnnotation()
pin.coordinate = poiCoodinates
self.mapView.addAnnotation(pin)
//add title to the pin
pin.title = location.name
}
I finally found the solution and here it goes:
import MapKit
class DetailViewController : UIViewController, MKMapViewDelegate {
//var mapType:UISegmentedControl!
//var showPointsOfInterest:UISwitch!
#IBOutlet weak var mapView: MKMapView!
#IBAction func showDirection(sender: AnyObject) {
}
var selectedLocation : LocationModel?
let locationManager = CLLocationManager()
var currentPlacemark:CLPlacemark?
//var segmentedControlAciton:UISegmentedControl!
#IBAction func myLocation(sender: AnyObject) {
// Request for a user's authorization for location services
locationManager.requestWhenInUseAuthorization()
let status = CLLocationManager.authorizationStatus()
if status == CLAuthorizationStatus.AuthorizedWhenInUse {
mapView.showsUserLocation = true
}
}
//
override func viewDidLoad() {
super.viewDidLoad()
// mapView.showsUserLocation = true
title = selectedLocation?.name
mapView.delegate = self
}
override func viewDidAppear(animated: Bool) {
// Create coordinates from location lat/long
var poiCoordinates: CLLocationCoordinate2D = CLLocationCoordinate2D()
poiCoordinates.latitude = CDouble(self.selectedLocation!.latitude!)!
poiCoordinates.longitude = CDouble(self.selectedLocation!.longitude!)!
// Zoom to region
let viewRegion: MKCoordinateRegion = MKCoordinateRegionMakeWithDistance(poiCoordinates, 750, 750)
self.mapView.setRegion(viewRegion, animated: true)
// Plot pin
let pin: MKPointAnnotation = MKPointAnnotation()
pin.coordinate = poiCoordinates
self.mapView.addAnnotation(pin)
//add title to the pin
pin.title = selectedLocation!.name
pin.subtitle=selectedLocation!.address
mapView.showsScale = true
}