Skip to content

Instantly share code, notes, and snippets.

@DouglasHennrich
Created July 6, 2019 17:21
Show Gist options
  • Save DouglasHennrich/831997e016cff95477c62a4e624c86fe to your computer and use it in GitHub Desktop.
Save DouglasHennrich/831997e016cff95477c62a4e624c86fe to your computer and use it in GitHub Desktop.
//
// MapViewController.swift
// Fleeter
//
// Created by Guilherme Leite Colares on 25/06/19.
// Copyright © 2019 Fleeter. All rights reserved.
//
import UIKit
import SideMenu
import Kingfisher
import CoreLocation
import GoogleMaps
import SwiftMessages
protocol MapViewControllerDelegate: class {
func mapViewController(didUpdateLocation location: LocationDetail.Location)
}
class MapViewController: UIViewController {
// MARK: - MarkerEnumType
enum MarkerType {
case origin
case destination
case driver
case user
}
// MARK: - Constants
struct Map {
static let cameraZoom: Float = 15.0
static let cameraPadding: CGFloat = 85.0
}
// MARK: - Properties
private let locationManager = CLLocationManager()
var userLocation: CLLocation? {
didSet {
if let coordinate = userLocation?.coordinate {
userLocationMarker.position = coordinate
}
}
}
lazy var userLocationMarker: GMSMarker = {
let marker = GMSMarker(position: CLLocationCoordinate2D(latitude: 0, longitude: 0))
marker.map = mapView
marker.tracksViewChanges = false
marker.iconView = MarkerIcon()
markers.append(marker)
return marker
}()
var driverMarker: GMSMarker?
var driverMarkerInfo: GMSMarker?
var originMarker: GMSMarker?
var originMarkerInfo: GMSMarker?
var destinationMarker: GMSMarker?
var destinationMarkerInfo: GMSMarker?
var onRoute: Bool = false
private var gradient: CAGradientLayer!
weak var mapViewDelegate: MapViewControllerDelegate?
var markers: [GMSMarker] = []
var getConfigModel: GetConfigViewModelProtocol?
var mapView: GMSMapView! {
didSet {
//mapView.delegate = self
mapView.isMyLocationEnabled = false
mapView.settings.tiltGestures = false
if let url = UserDefaults.standard.url(forKey: "MapStyleURL") {
mapView.mapStyle = try? GMSMapStyle(contentsOfFileURL: url)
}
}
}
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
mapView = GMSMapView(frame: view.frame)
view.insertSubview(mapView, at: 0)
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
getConfigModel = GetConfigViewModel()
getConfigModel?.requestConfig()
createMapGradient()
}
// MARK: - Actions
func createMapGradient() {
let gradientHeight: CGFloat = Constants.smallDevice ? 70 : 100
gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: -20, width: view.bounds.width, height: gradientHeight)
let transparentColor = UIColor(red: 246/255, green: 246/255, blue: 246/255, alpha: 1)
gradient.colors = [
transparentColor.withAlphaComponent(1).cgColor,
transparentColor.withAlphaComponent(1).cgColor,
transparentColor.withAlphaComponent(0.7).cgColor,
transparentColor.withAlphaComponent(0.0).cgColor
]
gradient.locations = [0, 0.3, 0.7, 1]
mapView.layer.addSublayer(gradient)
}
// MARK: - Location management
func checkLocationAuthorizationStatus() {
locationManager.locationServiceAuthorized { authorized in
if authorized {
self.locationManager.startUpdatingLocation()
} else {
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
}
}
}
// MARK: - Generic Functions
func showNoInternetConnectionMessage() {
let view = MessageView.viewFromNib(layout: .statusLine)
view.configureContent(body: "Sem conexão. Verifique sua internet.")
view.configureTheme(.error)
var config = SwiftMessages.Config()
config.presentationStyle = .top
config.duration = .forever
config.interactiveHide = false
config.preferredStatusBarStyle = .lightContent
SwiftMessages.show(config: config, view: view)
}
}
// MARK: - Route and map methods
extension MapViewController {
private func getMapViewVisibleHeight() -> CGFloat {
guard let viewController = UIApplication.shared.topMostViewController() as? BottomSheetController else {
return mapView.frame.height
}
return viewController.getVisibleHeight()
}
func goToUserLocation() {
if let coordinate = userLocation?.coordinate {
let camera = GMSCameraPosition.camera(withTarget: coordinate, zoom: Map.cameraZoom)
mapView.animate(to: camera)
}
}
func drawRoute(_ destination: Destination) {
guard let route = destination.routes.first else { return }
guard let path: GMSPath = GMSPath(fromEncodedPath: route.overviewPolyline.points) else { return }
let routePolyline = GMSPolyline(path: path)
routePolyline.strokeColor = UIColor.primaryColor
routePolyline.strokeWidth = 4.0
routePolyline.map = self.mapView
zoomOut()
}
func zoomOut() {
let bounds = markers.reduce(GMSCoordinateBounds()) {
$0.includingCoordinate($1.position)
}
let topModifier: CGFloat = Constants.smallDevice ? 70 : 160
let cameraUpdate = GMSCameraUpdate.fit(
bounds,
with: UIEdgeInsets(
top: topModifier,
left: Map.cameraPadding,
bottom: 300,
right: Map.cameraPadding*1.1))
mapView.animate(with: cameraUpdate)
}
}
// MARK: - Markers
extension MapViewController {
func cleanAllMarkers() {
markers = []
mapView.clear()
driverMarker = nil
originMarker = nil
destinationMarker = nil
}
private func setUserLocationMarker() {
markers = [userLocationMarker]
userLocationMarker.map = mapView
if let coordinate = userLocation?.coordinate {
let camera = GMSCameraPosition.camera(withTarget: coordinate, zoom: Map.cameraZoom)
mapView.animate(to: camera)
}
}
private func setDriverMarker(location: CLLocationCoordinate2D, infoTitle: String? = "Motorista", infoMessage: String? = nil) {
guard driverMarker == nil else { return }
driverMarker = VehicleMarker(position: location, vehicle: VehicleMarker.Vehicle.car)
guard let driverMarker = driverMarker else { return }
driverMarker.map = mapView
markers.append(driverMarker)
if infoMessage != nil {
if let infoView = OriginInfoView.loadFromNib() as? OriginInfoView {
infoView.titleLabel?.text = infoTitle
infoView.addressLabel?.text = infoMessage
driverMarkerInfo = InfoMarker(position: location, view: infoView)
guard let driverMarkerInfo = driverMarkerInfo else { return }
driverMarkerInfo.map = mapView
markers.append(driverMarkerInfo)
}
}
}
private func setOriginMarker(location: CLLocationCoordinate2D, address: String? = nil) {
guard originMarker == nil else { return }
originMarker = LocationMarker(position: location)
guard let originMarker = originMarker else { return }
originMarker.map = mapView
markers.append(originMarker)
if address != nil {
if let infoView = OriginInfoView.loadFromNib() as? OriginInfoView {
infoView.addressLabel?.text = address!
originMarkerInfo = InfoMarker(position: location, view: infoView)
guard let originMarkerInfo = originMarkerInfo else { return }
originMarkerInfo.map = mapView
markers.append(originMarkerInfo)
}
}
}
private func setDestinationMarker(
location: CLLocationCoordinate2D,
address: String? = nil,
timeTraffic: String? = nil) {
guard destinationMarker == nil else { return }
destinationMarker = LocationMarker(position: location)
guard let destinationMarker = destinationMarker else { return }
destinationMarker.map = mapView
if let infoView = DestinationInfoView.loadFromNib() as? DestinationInfoView {
infoView.addressLabel?.text = address
infoView.timeLabel?.text = timeTraffic
let infoMarker = InfoMarker(position: location, view: infoView)
infoMarker.map = mapView
markers.append(infoMarker)
}
markers.append(destinationMarker)
}
func setMarker(
type: MarkerType,
location: CLLocationCoordinate2D? = nil,
address: String? = nil,
timeTraffic: String? = nil) {
switch type {
case .user:
self.setUserLocationMarker()
case .origin:
guard let location = location else { return }
self.setOriginMarker(location: location, address: address)
case .destination:
guard let location = location else { return }
self.setDestinationMarker(location: location, address: address, timeTraffic: timeTraffic)
case .driver:
guard let location = location else { return }
self.setDriverMarker(location: location, infoMessage: timeTraffic)
}
}
func setInfoView(type: MarkerType, time: String? = nil) {
switch type {
case .driver:
guard driverMarkerInfo == nil else { return }
guard let driverMarker = driverMarker,
let infoView = OriginInfoView.loadFromNib() as? OriginInfoView else { return }
infoView.titleLabel?.text = "Motorista"
infoView.addressLabel?.text = time
driverMarkerInfo = InfoMarker(
position: driverMarker.position,
view: infoView)
guard let driverMarkerInfo = driverMarkerInfo else { return }
driverMarkerInfo.map = mapView
markers.append(driverMarkerInfo)
case .origin: break
case .destination: break
case .user: break
}
}
}
// MARK: - CLLocationManagerDelegate
extension MapViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
userLocation = location
User.current()?.lastLocation = location
if !onRoute {
let camera = GMSCameraPosition.camera(withTarget: location.coordinate, zoom: Map.cameraZoom)
mapView.animate(to: camera)
}
let coordinates = LocationDetail.Location(lat: location.coordinate.latitude,
lng: location.coordinate.longitude)
mapViewDelegate?.mapViewController(didUpdateLocation: coordinates)
locationManager.stopUpdatingLocation()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment