Created
July 6, 2019 17:21
-
-
Save DouglasHennrich/831997e016cff95477c62a4e624c86fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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