we are writing a code for navigation at swift. We implemented local database and downloaded our data into the app for offline navigation. But we have a problem. When we drawing road, its connecting beginning and endpoints
override func viewDidLoad() {
super.viewDidLoad()
CizimVeriler();
}
func CizimVeriler(){
var annotationCizim = getMapCizim()
var polyline2 : MKPolyline = MKPolyline()
var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()
for annotation in annotationCizim {
points.append(annotation.coordinate)
}
polyline2 = MKPolyline(coordinates: &points, count: points.count)
mapView.add(polyline2)
}
func getMapCizim() -> [Station] {
var annotationCizim:Array = [Station]()
annotationCizim.removeAll()
var stationCizim: NSArray?
do {
let secim = UserDefaults.standard.value(forKey: "RotaId") as! Int;
let filtrele = try self.database.prepare(self.RotaKoordinatTable.where(RotaKoorId == secim))
for rota in filtrele {
let x1 = Double(rota[(self.KoorX)])
let y1 = Double(rota[(self.KoorY)])
let annotation = Station(latitude: y1!, longitude: x1!)
annotation.title = "S1" as? String
annotationCizim.append(annotation)
}
} catch {
print(error)
}
return annotationCizim
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let polyLineRenderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
polyLineRenderer.strokeColor = #colorLiteral(red: 0.8961519599, green: 0.1830670238, blue: 0.06986772269, alpha: 1)
polyLineRenderer.lineWidth = 1
return polyLineRenderer
}
return MKOverlayRenderer()
}
Related
I'm currently building an Uber clone with Swift and Firebase, following Stephan Dowless' course on Udemy to learn more about MapKit, and so far it's going well, but I'm struggling to add a polyline overlay to the map, showing the route from the user's current location to the annotation (which is added to the mapView by tapping one of the search results displayed in a tableView).
I've looked for other similar questions on SO but haven't found anything that answers my question. I've also tried cloning other projects that use this feature (the completed Uber clone from the Udemy course, this Ray Wenderlich tutorial and this article on polylines using SwiftUI) to check whether it's my code that's the problem but they all present the same problem i.e. the annotations appear on the screen but the overlay doesn't appear at all.
In my app, tapping "Starbucks" on the tableView in this screen produces this screen (showing the annotation for Starbucks and user's current location, but no overlay).
Similarly, running the SwiftUI MapKit tutorial app from Medium mentioned previously shows this (both annotations but no overlay).
This leads me to believe that it's something wrong on my side. I've also tried running these apps on my phone (iPhone 7) with the same issues.
Here are the relevant lines of code:
Declaration of properties including route and mapView
// MARK:- Properties
private let mapView = MKMapView()
private var searchResults = [MKPlacemark]()
private var route: MKRoute?
mapView delegate set to self (function called when user is confirmed to be logged in)
private func configureMapView() {
view.addSubview(mapView)
mapView.frame = view.frame
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
}
MapView Functions
// MARK:- MapView Functions
extension HomeViewController: MKMapViewDelegate {
private func generatePolyline(toDestination destination: MKMapItem) {
let request = MKDirections.Request()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.transportType = .automobile
let directionRequest = MKDirections(request: request)
directionRequest.calculate { (response, error) in
guard let response = response else { return }
self.route = response.routes[0]
guard let polyline = self.route?.polyline else { return }
self.mapView.addOverlay(polyline)
}
}
private func searchBy(naturalLanguageQuery: String, completion: #escaping([MKPlacemark]) -> Void) {
var results = [MKPlacemark]()
let request = MKLocalSearch.Request()
request.region = mapView.region
request.naturalLanguageQuery = naturalLanguageQuery
let search = MKLocalSearch(request: request)
search.start { (response, error) in
guard let response = response else { return }
response.mapItems.forEach { (item) in
results.append(item.placemark)
}
completion(results)
}
}
// Change driver annotation appearance to Uber arrow
public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? DriverAnnotation {
let view = MKAnnotationView(annotation: annotation, reuseIdentifier: DriverAnnotation.identifier)
view.image = #imageLiteral(resourceName: "chevron-sign-to-right")
return view
}
return nil
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let route = self.route {
let polyline = route.polyline
let lineRenderer = MKPolylineRenderer(overlay: polyline)
lineRenderer.strokeColor = .mainBlueTint
lineRenderer.lineWidth = 4
return lineRenderer
}
return MKOverlayRenderer()
}
}
TableView didSelectRowAt Method
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let placemark = self.searchResults[indexPath.row]
configureActionButtonState(config: .dismissActionView)
let destination = MKMapItem(placemark: placemark)
self.generatePolyline(toDestination: destination)
self.dismissInputView { _ in
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
self.mapView.addAnnotation(annotation)
self.mapView.selectAnnotation(annotation, animated: true)
}
}
Finally, here's the whole view controller, just in case I've missed anything above. Please let me know if any further information is required to answer the question and I'll provide it.
Entire view controller
import UIKit
import Firebase
import MapKit
private enum ActionButtonConfiguration {
case showMenu
case dismissActionView
init() {
self = .showMenu
}
}
class HomeViewController: UIViewController {
// MARK:- Properties
private let mapView = MKMapView()
private let locationManager = LocationHandler.shared.locationManager
private let inputActivationView = LocationInputActivationView()
private let locationInputView = LocationInputView()
private var searchResults = [MKPlacemark]()
private var actionButtonConfig = ActionButtonConfiguration()
private var route: MKRoute?
private let tableView = UITableView()
private var user: User? {
didSet {
locationInputView.user = user
}
}
private let actionButton: UIButton = {
let button = UIButton()
button.setImage(#imageLiteral(resourceName: "baseline_menu_black_36dp").withRenderingMode(.alwaysOriginal), for: .normal)
button.addTarget(self, action: #selector(didTapActionButton), for: .touchUpInside)
return button
}()
// MARK:- Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
checkIfUserLoggedIn()
locationManagerDidChangeAuthorization(locationManager!)
}
// MARK:- Selectors
#objc private func didTapActionButton() {
switch actionButtonConfig {
case .showMenu:
print("Show menu")
case .dismissActionView:
removeAnnotationsAndOverlays()
UIView.animate(withDuration: 0.3) {
self.configureActionButtonState(config: .showMenu)
self.inputActivationView.alpha = 1
}
}
}
// MARK:- API
private func fetchUserData() {
guard let currentUserId = Auth.auth().currentUser?.uid else { return }
Service.shared.fetchUserData(uid: currentUserId) { user in
self.user = user
}
}
// N.B. Service.shared.fetchDrivers automatically gets called every time the location of the driver changes since it is observing the database via geofire (see definition of this within Service.swift)
private func fetchDrivers() {
guard let location = locationManager?.location else { return }
Service.shared.fetchDrivers(location: location) { (driver) in
guard let coordinate = driver.location?.coordinate else { return }
let annotation = DriverAnnotation(uid: driver.uid, coordinate: coordinate)
var driverIsVisible: Bool {
return self.mapView.annotations.contains { annotation -> Bool in
guard let driverAnnotation = annotation as? DriverAnnotation else { return false }
if driverAnnotation.uid == driver.uid {
// Driver is already visible - update driver location whenever this function is called
driverAnnotation.updateAnnotationPosition(withCoordinate: coordinate)
return true
}
// Driver is not visible
return false
}
}
// If driver is not visible then add to map
if !driverIsVisible {
self.mapView.addAnnotation(annotation)
}
}
}
private func checkIfUserLoggedIn() {
if Auth.auth().currentUser == nil {
// User is not logged in
print("DEBUG: User is not logged in")
DispatchQueue.main.async {
let nav = UINavigationController(rootViewController: LoginViewController())
nav.isModalInPresentation = true
nav.modalPresentationStyle = .fullScreen
self.present(nav, animated: true, completion: nil)
}
} else {
// User is logged in
configure()
}
}
private func logOut() {
do {
try Auth.auth().signOut()
DispatchQueue.main.async {
let nav = UINavigationController(rootViewController: LoginViewController())
nav.isModalInPresentation = true
nav.modalPresentationStyle = .fullScreen
self.present(nav, animated: true, completion: nil)
}
} catch {
print("DEBUG: Error signing user out: \(error)")
}
}
// MARK:- Public Helper Functions
public func configure() {
configureUI()
fetchUserData()
fetchDrivers()
}
public func configureUI() {
configureMapView()
configureActionButton()
configureInputActivationView()
configureTableView()
}
// MARK:- Private Helper Functions
private func configureActionButton() {
view.addSubview(actionButton)
actionButton.anchor(top: view.safeAreaLayoutGuide.topAnchor, left: view.safeAreaLayoutGuide.leftAnchor,
paddingTop: 16, paddingLeft: 16, width: 30, height: 30)
}
private func configureActionButtonState(config: ActionButtonConfiguration) {
switch config {
case .showMenu:
self.actionButton.setImage(#imageLiteral(resourceName: "baseline_menu_black_36dp").withRenderingMode(.alwaysOriginal), for: .normal)
self.actionButtonConfig = .showMenu
case .dismissActionView:
self.actionButton.setImage(#imageLiteral(resourceName: "baseline_arrow_back_black_36dp-1").withRenderingMode(.alwaysOriginal), for: .normal)
self.actionButtonConfig = .dismissActionView
}
}
private func configureMapView() {
view.addSubview(mapView)
mapView.frame = view.frame
mapView.delegate = self
mapView.showsUserLocation = true
mapView.userTrackingMode = .follow
}
private func configureInputActivationView() {
inputActivationView.delegate = self
view.addSubview(inputActivationView)
inputActivationView.centerX(inView: view)
inputActivationView.anchor(top: actionButton.bottomAnchor, left: view.safeAreaLayoutGuide.leftAnchor, right: view.safeAreaLayoutGuide.rightAnchor, paddingTop: 18, paddingLeft: 20, paddingRight: 20, height: 40)
// Animate inputActivationView (fade in)
inputActivationView.alpha = 0
UIView.animate(withDuration: 2) {
self.inputActivationView.alpha = 1
}
}
private func configureLocationInputView() {
locationInputView.delegate = self
view.addSubview(locationInputView)
locationInputView.anchor(top: view.topAnchor, left: view.leftAnchor, right: view.rightAnchor, height: 200)
locationInputView.alpha = 0
UIView.animate(withDuration: 0.5) {
self.locationInputView.alpha = 1
} completion: { _ in
print("DEBUG: Present table view")
UIView.animate(withDuration: 0.3) {
self.tableView.frame.origin.y = self.locationInputView.frame.height
}
}
}
private func configureTableView() {
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.register(LocationTableViewCell.self, forCellReuseIdentifier: LocationTableViewCell.identifier)
tableView.rowHeight = 60
tableView.tableFooterView = UIView()
let height = view.frame.height - locationInputView.frame.height
tableView.frame = CGRect(x: 0, y: view.frame.height, width: view.frame.width, height: height)
}
private func dismissInputView(completion: ((Bool) -> Void)? = nil) {
UIView.animate(withDuration: 0.3, animations: {
self.locationInputView.alpha = 0
self.tableView.frame.origin.y = self.view.frame.height
self.locationInputView.removeFromSuperview()
}, completion: completion)
}
private func removeAnnotationsAndOverlays() {
mapView.annotations.forEach { annotation in
if let anno = annotation as? MKPointAnnotation {
mapView.removeAnnotation(anno)
}
}
if mapView.overlays.count > 0 {
mapView.removeOverlay(mapView.overlays[0])
}
}
}
// MARK:- MapView Functions
extension HomeViewController: MKMapViewDelegate {
private func generatePolyline(toDestination destination: MKMapItem) {
let request = MKDirections.Request()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.transportType = .automobile
let directionRequest = MKDirections(request: request)
directionRequest.calculate { (response, error) in
guard let response = response else { return }
self.route = response.routes[0]
guard let polyline = self.route?.polyline else { return }
self.mapView.addOverlay(polyline)
}
}
private func searchBy(naturalLanguageQuery: String, completion: #escaping([MKPlacemark]) -> Void) {
var results = [MKPlacemark]()
let request = MKLocalSearch.Request()
request.region = mapView.region
request.naturalLanguageQuery = naturalLanguageQuery
let search = MKLocalSearch(request: request)
search.start { (response, error) in
guard let response = response else { return }
response.mapItems.forEach { (item) in
results.append(item.placemark)
}
completion(results)
}
}
// Change driver annotation appearance to Uber arrow
public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? DriverAnnotation {
let view = MKAnnotationView(annotation: annotation, reuseIdentifier: DriverAnnotation.identifier)
view.image = #imageLiteral(resourceName: "chevron-sign-to-right")
return view
}
return nil
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if let route = self.route {
let polyline = route.polyline
let lineRenderer = MKPolylineRenderer(overlay: polyline)
lineRenderer.strokeColor = .mainBlueTint
lineRenderer.lineWidth = 3
return lineRenderer
}
return MKOverlayRenderer()
}
}
// MARK:- Location Manager Services
extension HomeViewController {
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .notDetermined:
print("DEBUG: Not determined")
locationManager?.requestWhenInUseAuthorization()
case .restricted:
break
case .denied:
break
case .authorizedAlways:
print("DEBUG: Auth always")
locationManager?.startUpdatingLocation()
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
case .authorizedWhenInUse:
print("DEBUG: Auth when in use")
locationManager?.requestAlwaysAuthorization()
#unknown default:
break
}
}
}
// MARK:- Input Activation View Delegate Methods
extension HomeViewController: LocationInputActivationViewDelegate {
func presentLocationInputView() {
configureLocationInputView()
self.inputActivationView.alpha = 0
}
}
// MARK:- Input View Delegate Methods
extension HomeViewController: LocationInputViewDelegate {
func executeSearch(query: String) {
searchBy(naturalLanguageQuery: query) { (results) in
print("DEBUG: Placemarks are \(results)")
self.searchResults = results
self.tableView.reloadData()
}
}
func dismissLocationInputView() {
dismissInputView()
UIView.animate(withDuration: 0.5) {
self.inputActivationView.alpha = 1
}
}
}
// MARK:- TableView Delegate and Datasource Methods
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
2
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "test"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 2 : searchResults.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: LocationTableViewCell.identifier, for: indexPath) as! LocationTableViewCell
if indexPath.section == 1 {
cell.placemark = searchResults[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let placemark = self.searchResults[indexPath.row]
configureActionButtonState(config: .dismissActionView)
let destination = MKMapItem(placemark: placemark)
self.generatePolyline(toDestination: destination)
self.dismissInputView { _ in
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
self.mapView.addAnnotation(annotation)
self.mapView.selectAnnotation(annotation, animated: true)
}
}
}
Here's the output in the debug window also, not sure if it's relevant:
2021-01-26 19:36:40.853479+0700 Uber[17163:1579722] [Default] InfoLog PolylineOverlayFillShader: WARNING: 0:42: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:48: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:54: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:66: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:68: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:72: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:74: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:78: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
WARNING: 0:80: Overflow in implicit constant conversion, minimum range for lowp float is (-2,2)
Thanks in advance!
I have created a simplified version of this - with a hard-coded destination, but creating the route as you do, and this works very nicely.
private func generatePolyline(toDestination destination: MKMapItem) {
let request = MKDirections.Request()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.transportType = .automobile
let directionRequest = MKDirections(request: request)
directionRequest.calculate { (response, error) in
guard let response = response else { return }
self.route = response.routes[0]
guard let polyline = self.route?.polyline else { return }
self.mapView.addOverlay(polyline)
print("update map?")
}
}
the only thing I have added here is the debug print statement at the end - always nice to know that something should be happening, but always good to know it actually has!
I called the function from a simple test button
#IBAction func cmdButton(_ sender: Any) {
// for testing - Edinburgh Castle
generatePolyline(toDestination: MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 55.9483, longitude: -3.1981), addressDictionary: nil)))
}
The renderer is very simple, and includes a test print as above
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let pr = MKPolylineRenderer(overlay: overlay)
pr.strokeColor = UIColor.red.withAlphaComponent(0.5)
pr.lineWidth = 7
print("rendererFor overlay")
return pr
}
If you're seeing the debug print comments, you should be ok. Let me know how you get on...
After digging a little deeper, the reason is that I'm in Phnom Penh, Cambodia. Apple Maps doesn't have the ability to give directions in Cambodia. Guess I'll have to resort to Google Maps if I want a line drawn from one point to another then.
I am struggling to try and Highlight the road between 2 points using MapKit. All I don't want directions i just want to try and Highlight the road between these two points.
My code is:
import UIKit
import MapKit
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView!
struct Points {
var name: String
var lattitude: CLLocationDegrees
var longtitude: CLLocationDegrees
}
override func viewDidLoad() {
super.viewDidLoad()
let points = [
Points(name: "Point 1", lattitude: 52.100525, longtitude: -9.623071),
Points(name: "Point 2", lattitude: 52.07241, longtitude: -9.575299)
]
fetchPointsOnMap(points)
}
func fetchPointsOnMap(_ points: [Points]) {
for points in points {
let annotations = MKPointAnnotation()
annotations.title = points.name
annotations.coordinate = CLLocationCoordinate2D(latitude:
points.lattitude, longitude: points.longtitude)
mapView.addAnnotation(annotations)
}
}
}`
You can draw a line:
directionsRequest.transportType = MKDirectionsTransportType.automobile
//Draw polyline by using MKRoute so it follows the street roads...
for (k, item) in arrayarrayPlacemarks.enumerated() {
if k < (arrayarrayPlacemarks.count - 1) {
directionsRequest.source = item
directionsRequest.destination = arrayarrayPlacemarks[k+1]
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response:MKDirections.Response!, error: Error!) -> Void in
if error == nil {
self.locRoute = response.routes[0] as? MKRoute
let geodesic:MKPolyline = self.locRoute!.polyline
self.mapView.addOverlay(geodesic)
}
}
}
}
Delegate:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKPolyline.self){
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.fillColor = UIColor.blue
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}
I try to add a Polyline to the map, but it is not visible.
locationManager.startUpdatingLocation()
guard let locValue: CLLocationCoordinate2D =
locationManager.location?.coordinate else { return }
Map.setCenter(locValue, animated: true)
if !locations.contains(where: {$0.latitude == locValue.latitude && $0.longitude == locValue.longitude}) {
locations.append(locValue)
NSLog("Add: %f %f -> Count: %i", locValue.latitude, locValue.longitude, locations.count)
let polyline = MKPolyline(coordinates: &locations, count: locations.count)
Map.addOverlay(mapView(Map, rendererFor: polyline).overlay)
}
"My" mapView function:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let polyLine = overlay
let polyLineRenderer = MKPolylineRenderer(overlay: polyLine)
polyLineRenderer.strokeColor = UIColor.red
polyLineRenderer.lineWidth = 5.0
return polyLineRenderer
}
You can try
self.map.delegate = self
let polyline = MKPolyline(coordinates:locations, count: locations.count)
self.map.addOverlay(routeLine)
I would like to take a screenshot of ongoing VideoCaptureView during a call in iOS Swift. I used QuickBlox.
I have used below code that return black image
public extension UIView {
public func snapshotImage() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque,0)
drawHierarchy(in: bounds, afterScreenUpdates: false)
let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImage
}
public func snapshotView() -> UIView? {
if let snapshotImage = snapshotImage() {
return UIImageView(image: snapshotImage)
} else {
return nil
}
}
}
let snapshot = view.snapshotView()
Try this
fileprivate func captureUIImageFromUIView(_ view:UIView?) -> UIImage {
guard (view != nil) else{
// if the view is nil (it's happened to me) return an alternative image
let errorImage = UIImage(named: "Logo.png")
return errorImage!
}
// if the view is all good then convert the image inside the view to a uiimage
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(size: view!.bounds.size)
let capturedImage = renderer.image {
(ctx) in
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
}
return capturedImage
} else {
UIGraphicsBeginImageContextWithOptions((view!.bounds.size), view!.isOpaque, 0.0)
view!.drawHierarchy(in: view!.bounds, afterScreenUpdates: false)
let capturedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return capturedImage!
}
}
Call
let pdfImage = self.captureUIImageFromUIView(self.containerView)
//
// ViewController.swift
// GooglePlace-AutoComplete
//
// Created by infos on 7/10/18.
// Copyright © 2018 infos. All rights reserved.
//
import UIKit
import GoogleMaps
import GooglePlaces
import SwiftyJSON
import Alamofire
enum Location {
case startLocation
case destinationLocation
}
class ViewController: UIViewController , GMSMapViewDelegate , CLLocationManagerDelegate,UITextFieldDelegate {
#IBOutlet weak var googleMaps: GMSMapView!
#IBOutlet weak var startLocation: UITextField!
#IBOutlet weak var destinationLocation: UITextField!
var locationManager = CLLocationManager()
var locationSelected = Location.startLocation
var polyline = GMSPolyline()
var locationStart = CLLocation()
var locationEnd = CLLocation()
override func viewDidLoad() {
super.viewDidLoad()
GMSPlacesClient.provideAPIKey("AIzaSyC55Dq1qPH7EM_uiAVf-8QuxJtf2W1viQs")
GMSServices.provideAPIKey("AIzaSyC55Dq1qPH7EM_uiAVf-8QuxJtf2W1viQs")
// Create a GMSCameraPosition that tells the map to display the
let camera = GMSCameraPosition.camera(withLatitude: 13.082680,
longitude: 80.270718,
zoom: 10.0,
bearing: 30,
viewingAngle: 40)
//Setting the googleView
googleMaps.camera = camera
googleMaps.delegate = self
googleMaps.isMyLocationEnabled = true
googleMaps.settings.myLocationButton = true
googleMaps.settings.compassButton = true
googleMaps.settings.zoomGestures = true
googleMaps.animate(to: camera)
self.view.addSubview(googleMaps)
//Setting the start and end location
let origin = "\(13.082680),\(80.270718)"
let destination = "\(15.912900),\(79.739987)"
let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving"
//Rrequesting Alamofire and SwiftyJSON
Alamofire.request(url).responseJSON { response in
print(response.request as Any) // original URL request
print(response.response as Any) // HTTP URL response
print(response.data as Any) // server data
print(response.result) // result of response serialization
do {
let json = try JSON(data: response.data!)
let routes = json["routes"].arrayValue
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
let points = routeOverviewPolyline?["points"]?.stringValue
let path = GMSPath.init(fromEncodedPath: points!)
let polyline = GMSPolyline.init(path: path)
polyline.strokeColor = UIColor.blue
polyline.strokeWidth = 2
polyline.map = self.googleMaps
}
}
catch {
}
}
// Creates a marker in the center of the map.
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: 28.524555, longitude: 77.275111)
marker.title = "Mobiloitte"
marker.snippet = "India"
marker.map = googleMaps
//28.643091, 77.218280
let marker1 = GMSMarker()
marker1.position = CLLocationCoordinate2D(latitude: 28.643091, longitude: 77.218280)
marker1.title = "NewDelhi"
marker1.snippet = "India"
marker1.map = googleMaps
}
// MARK: function for create a marker pin on map
func createMarker(titleMarker: String, iconMarker: UIImage, latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let marker = GMSMarker()
marker.position = CLLocationCoordinate2DMake(latitude, longitude)
marker.isDraggable=true
marker.title = titleMarker
marker.icon = iconMarker
marker.map = googleMaps
}
//MARK: - Location Manager delegates
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error to get location : \(error)")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
// let camera = GMSCameraPosition.camera(withLatitude: (location?.coordinate.latitude)!, longitude: (location?.coordinate.longitude)!, zoom: 17.0)
let locationMobi = CLLocation(latitude: 28.524555, longitude: 77.275111)
drawPath(startLocation: location!, endLocation: locationMobi)
//self.googleMaps?.animate(to: camera)
self.locationManager.stopUpdatingLocation()
}
// MARK: - GMSMapViewDelegate
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
googleMaps.isMyLocationEnabled = true
}
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
googleMaps.isMyLocationEnabled = true
if (gesture) {
mapView.selectedMarker = nil
}
}
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
googleMaps.isMyLocationEnabled = true
return false
}
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
print("COORDINATE \(coordinate)") // when you tapped coordinate
}
func didTapMyLocationButton(for mapView: GMSMapView) -> Bool {
googleMaps.isMyLocationEnabled = true
googleMaps.selectedMarker = nil
return false
}
//MARK: - Marker Delegate
func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) {
}
func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) {
}
func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
self.googleMaps.reloadInputViews()
//self.polyline.map = nil;
print("marker dragged to location: \(marker.position.latitude),\(marker.position.longitude)")
let locationMobi = CLLocation(latitude: marker.position.latitude, longitude: marker.position.longitude)
self.drawPath(startLocation: locationMobi, endLocation: locationEnd)
}
//MARK: - this is function for create direction path, from start location to desination location
func drawPath(startLocation: CLLocation, endLocation: CLLocation)
{
let origin = "\(startLocation.coordinate.latitude),\(startLocation.coordinate.longitude)"
let destination = "\(endLocation.coordinate.latitude),\(endLocation.coordinate.longitude)"
self.polyline.map = nil
//self.googleMaps.clear()
let url = "https://maps.googleapis.com/maps/api/directions/json?origin=\(origin)&destination=\(destination)&mode=driving"
Alamofire.request(url).responseJSON { response in
print(response.request as Any) // original URL request
print(response.response as Any) // HTTP URL response
print(response.data as Any) // server data
print(response.result as Any) // result of response serialization
do {
let json = try JSON(data: response.data!)
let routes = json["routes"].arrayValue
// print route using Polyline
for route in routes
{
let routeOverviewPolyline = route["overview_polyline"].dictionary
let points = routeOverviewPolyline?["points"]?.stringValue
let path = GMSPath.init(fromEncodedPath: points!)
self.polyline = GMSPolyline.init(path: path)
self.polyline.strokeWidth = 2
self.polyline.strokeColor = UIColor.red
self.polyline.map = self.googleMaps
}
} catch {
}
}
}
// MARK: when start location tap, this will open the search location
#IBAction func openStartLocation(_ sender: UIButton) {
let autoCompleteController = GMSAutocompleteViewController()
autoCompleteController.delegate = self
// selected location
locationSelected = .startLocation
// Change text color
UISearchBar.appearance().setTextColor(color: UIColor.black)
self.locationManager.stopUpdatingLocation()
self.present(autoCompleteController, animated: true, completion: nil)
}
// MARK: when destination location tap, this will open the search location
#IBAction func openDestinationLocation(_ sender: UIButton) {
let autoCompleteController = GMSAutocompleteViewController()
autoCompleteController.delegate = self
// selected location
locationSelected = .destinationLocation
// Change text color
UISearchBar.appearance().setTextColor(color: UIColor.black)
self.locationManager.stopUpdatingLocation()
self.present(autoCompleteController, animated: true, completion: nil)
}
// MARK: SHOW DIRECTION WITH BUTTON
#IBAction func showDirection(_ sender: UIButton) {
// when button direction tapped, must call drawpath func
self.drawPath(startLocation: locationStart, endLocation: locationEnd)
}
}
// MARK: - GMS Auto Complete Delegate, for autocomplete search location
extension ViewController: GMSAutocompleteViewControllerDelegate {
func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
print("Error \(error)")
}
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
// Change map location
let camera = GMSCameraPosition.camera(withLatitude: place.coordinate.latitude, longitude: place.coordinate.longitude, zoom: 16.0
)
// set coordinate to text
if locationSelected == .startLocation {
if (self.locationManager.location?.coordinate.longitude) != nil {
startLocation.text = "\(place.coordinate.latitude), \(place.coordinate.longitude)"
locationStart = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
createMarker(titleMarker: "Location Start", iconMarker: #imageLiteral(resourceName: "images"), latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
}else {
// handle the error by declaring default value
}
} else {
if (self.locationManager.location?.coordinate.longitude) != nil {
destinationLocation.text = "\(place.coordinate.latitude), \(place.coordinate.longitude)"
locationEnd = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
createMarker(titleMarker: "Location End", iconMarker: #imageLiteral(resourceName: "images"), latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
}else {
// handle the error by declaring default value
}
}
self.googleMaps.camera = camera
self.dismiss(animated: true, completion: nil)
}
func wasCancelled(_ viewController: GMSAutocompleteViewController) {
self.dismiss(animated: true, completion: nil)
}
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
textField.resignFirstResponder()
return true
}
public extension UISearchBar {
public func setTextColor(color: UIColor) {
let svs = subviews.flatMap { $0.subviews }
guard let tf = (svs.filter { $0 is UITextField }).first as? UITextField else { return }
tf.textColor = color
}
}
Here is working code to take a screenshot of ongoing video during a call in QuickBlox
#IBOutlet weak var stackView: UIStackView!
let stillImageOutput = AVCaptureStillImageOutput()
override func viewDidLoad() {
super.viewDidLoad()
QBRTCClient.initializeRTC()
QBRTCClient.instance().add(self)
cofigureVideo()
}
func cofigureVideo() {
QBRTCConfig.mediaStreamConfiguration().videoCodec = .H264
QBRTCConfig.setAnswerTimeInterval(30)
QBRTCConfig.setStatsReportTimeInterval(5)
let videoFormat = QBRTCVideoFormat.init()
videoFormat.frameRate = 30
videoFormat.pixelFormat = .format420f
videoFormat.width = 640
videoFormat.height = 480
self.videoCapture = QBRTCCameraCapture.init(videoFormat: videoFormat, position: .front)
self.videoCapture.previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.videoCapture.startSession {
self.stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
if self.videoCapture.captureSession.canAddOutput(self.stillImageOutput) {
self.videoCapture.captureSession.addOutput(self.stillImageOutput)
}
let localView = LocalVideoView.init(withPreviewLayer:self.videoCapture.previewLayer)
self.stackView.addArrangedSubview(localView)
}
}
Take photo Button Click
#IBAction func TakePhotoTapped(_ sender: Any) {
if let videoConnection = stillImageOutput.connection(with: AVMediaType.video) {
stillImageOutput.captureStillImageAsynchronously(from: videoConnection) {
(imageDataSampleBuffer, error) -> Void in
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!)
if let image = UIImage(data: imageData!){
// Your image is Here
}
}
}
}
For the practice of MapKit in iOS using Swift 2.0 targeted version iOS 8.0 drawing path between two points I am getting errors in my code that you can see above.
Here is my practice code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet var map: MKMapView!
var geocoder:CLGeocoder = CLGeocoder()
var location:CLLocation = CLLocation(latitude: 38, longitude: -77)
var next:CLLocation = CLLocation(latitude: 38.21, longitude: -77.21)
var locMark:MKPlacemark?
var destMark:MKPlacemark?
var manager:CLLocationManager = CLLocationManager()
var source:MKMapItem?
var destination:MKMapItem?
var request:MKDirectionsRequest = MKDirectionsRequest()
var directions:MKDirections = MKDirections()
var directionsResponse:MKDirectionsResponse = MKDirectionsResponse()
var route:MKRoute = MKRoute()
override func viewDidLoad() {
super.viewDidLoad()
manager.requestAlwaysAuthorization()
map.mapType = MKMapType.Satellite
locMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), addressDictionary: nil)
destMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(next.coordinate.latitude, next.coordinate.longitude), addressDictionary: nil)
source = MKMapItem(placemark: locMark)
destination = MKMapItem(placemark: destMark)
request.setSource(source)
request.setDestination(destination)
request.transportType = MKDirectionsTransportType.Automobile
request.requestsAlternateRoutes = true
directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse?, error:NSError?) -> Void in
if error == nil {
self.directionsResponse = response!
self.route = self.directionsResponse.routes[0] as! MKRoute
map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
} else {
println(error)
}
}
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
println("redenrerForOverlay")
if(overlay.isKindOfClass(MKPolyline)) {
var renderer: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = Colors.psnGreen
renderer.lineWidth = 5
return renderer
}
return nil
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayView! {
println("ViewForOverlay")
if (overlay.isKindOfClass(MKPolyline)) {
var lineView: MKPolylineView = MKPolylineView(overlay: overlay)
lineView.backgroundColor = Colors.psnGreen
return lineView;
}
return nil;
}
}
Zeeshan you just need to delete those two lines and add the two lines from Mark Answer , this below code is working fine:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet var map: MKMapView!
var geocoder:CLGeocoder = CLGeocoder()
var location:CLLocation = CLLocation(latitude: 38, longitude: -77)
var next:CLLocation = CLLocation(latitude: 38.21, longitude: -77.21)
var locMark:MKPlacemark?
var destMark:MKPlacemark?
var manager:CLLocationManager = CLLocationManager()
var source:MKMapItem?
var destination:MKMapItem?
var request:MKDirectionsRequest = MKDirectionsRequest()
var directions:MKDirections = MKDirections()
var directionsResponse:MKDirectionsResponse = MKDirectionsResponse()
var route:MKRoute = MKRoute()
override func viewDidLoad() {
super.viewDidLoad()
manager.requestAlwaysAuthorization()
map.mapType = MKMapType.Satellite
locMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), addressDictionary: nil)
destMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(next.coordinate.latitude, next.coordinate.longitude), addressDictionary: nil)
source = MKMapItem(placemark: locMark)
destination = MKMapItem(placemark: destMark)
request.source = source
request.destination = destination
request.transportType = MKDirectionsTransportType.Automobile
request.requestsAlternateRoutes = true
directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse?, error:NSError?) -> Void in
if error == nil {
self.directionsResponse = response!
self.route = self.directionsResponse.routes[0] as! MKRoute
map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
} else {
print(error)
}
}
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
print("redenrerForOverlay")
if(overlay.isKindOfClass(MKPolyline)) {
var renderer: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = Colors.psnGreen
renderer.lineWidth = 5
return renderer
}
return nil
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayView! {
print("ViewForOverlay")
if (overlay.isKindOfClass(MKPolyline)) {
var lineView: MKPolylineView = MKPolylineView(overlay: overlay)
lineView.backgroundColor = Colors.psnGreen
return lineView;
}
return nil;
}
}
Try changing the two lines to this:
request.source = source
request.destination = destination
Swift uses the property directly, rather than an explicit setter (which is only available in Obj-C).