Verified Commit b7e60caf authored by asahiocean's avatar asahiocean 🚀
Browse files

Setting up location and delegates

parent 69c05bd6
......@@ -58,6 +58,24 @@
3DD5F37D25F85F0400923766 /* clearButtonSetup+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F37C25F85F0400923766 /* clearButtonSetup+Model.swift */; };
3DD5F37E25F85F0400923766 /* clearButtonSetup+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F37C25F85F0400923766 /* clearButtonSetup+Model.swift */; };
3DD5F37F25F85F0400923766 /* clearButtonSetup+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F37C25F85F0400923766 /* clearButtonSetup+Model.swift */; };
3DD5F38625F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38525F85FEE00923766 /* MKMapViewDelegate+ViewController.swift */; };
3DD5F38725F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38525F85FEE00923766 /* MKMapViewDelegate+ViewController.swift */; };
3DD5F38825F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38525F85FEE00923766 /* MKMapViewDelegate+ViewController.swift */; };
3DD5F39025F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38F25F8601600923766 /* alertAuthorizedWhenInUse.swift */; };
3DD5F39125F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38F25F8601600923766 /* alertAuthorizedWhenInUse.swift */; };
3DD5F39225F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F38F25F8601600923766 /* alertAuthorizedWhenInUse.swift */; };
3DD5F39825F8603600923766 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F39725F8603600923766 /* LocationManager.swift */; };
3DD5F39925F8603600923766 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F39725F8603600923766 /* LocationManager.swift */; };
3DD5F39A25F8603600923766 /* LocationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F39725F8603600923766 /* LocationManager.swift */; };
3DD5F3A325F8609300923766 /* ModelDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3A225F8609300923766 /* ModelDelegate+ViewController.swift */; };
3DD5F3A425F8609300923766 /* ModelDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3A225F8609300923766 /* ModelDelegate+ViewController.swift */; };
3DD5F3A525F8609300923766 /* ModelDelegate+ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3A225F8609300923766 /* ModelDelegate+ViewController.swift */; };
3DD5F3AD25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3AC25F860ED00923766 /* CLLocationCoordinate2D.swift */; };
3DD5F3AE25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3AC25F860ED00923766 /* CLLocationCoordinate2D.swift */; };
3DD5F3AF25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3AC25F860ED00923766 /* CLLocationCoordinate2D.swift */; };
3DD5F3B425F8611600923766 /* MKPolyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3B325F8611600923766 /* MKPolyline.swift */; };
3DD5F3B525F8611600923766 /* MKPolyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3B325F8611600923766 /* MKPolyline.swift */; };
3DD5F3B625F8611600923766 /* MKPolyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DD5F3B325F8611600923766 /* MKPolyline.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
......@@ -105,6 +123,12 @@
3DD5F36E25F85E1E00923766 /* action+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "action+Model.swift"; sourceTree = "<group>"; };
3DD5F37525F85E5700923766 /* UIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButton.swift; sourceTree = "<group>"; };
3DD5F37C25F85F0400923766 /* clearButtonSetup+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "clearButtonSetup+Model.swift"; sourceTree = "<group>"; };
3DD5F38525F85FEE00923766 /* MKMapViewDelegate+ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MKMapViewDelegate+ViewController.swift"; sourceTree = "<group>"; };
3DD5F38F25F8601600923766 /* alertAuthorizedWhenInUse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = alertAuthorizedWhenInUse.swift; sourceTree = "<group>"; };
3DD5F39725F8603600923766 /* LocationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationManager.swift; sourceTree = "<group>"; };
3DD5F3A225F8609300923766 /* ModelDelegate+ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ModelDelegate+ViewController.swift"; sourceTree = "<group>"; };
3DD5F3AC25F860ED00923766 /* CLLocationCoordinate2D.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CLLocationCoordinate2D.swift; sourceTree = "<group>"; };
3DD5F3B325F8611600923766 /* MKPolyline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MKPolyline.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -222,6 +246,7 @@
3DD5F2D125F8567C00923766 /* Model */ = {
isa = PBXGroup;
children = (
3DD5F39625F8603000923766 /* LocationManager */,
3DD5F35025F85D2800923766 /* Buttons */,
3DD5F32B25F85B1A00923766 /* PinAnnotation */,
3DD5F2EC25F8585D00923766 /* Model.swift */,
......@@ -267,6 +292,7 @@
isa = PBXGroup;
children = (
3DD5F31F25F85A5B00923766 /* Extensions */,
3DD5F38F25F8601600923766 /* alertAuthorizedWhenInUse.swift */,
);
path = Helpers;
sourceTree = "<group>";
......@@ -277,6 +303,8 @@
3DD5F32125F85A7100923766 /* MKMarkerAnnotationView.swift */,
3DD5F36725F85DFB00923766 /* UIEdgeInsets.swift */,
3DD5F37525F85E5700923766 /* UIButton.swift */,
3DD5F3AC25F860ED00923766 /* CLLocationCoordinate2D.swift */,
3DD5F3B325F8611600923766 /* MKPolyline.swift */,
);
path = Extensions;
sourceTree = "<group>";
......@@ -301,6 +329,7 @@
isa = PBXGroup;
children = (
3DD5F26D25F853E900923766 /* ViewController.swift */,
3DD5F38325F85FDA00923766 /* Delegates */,
3DD5F34325F85C8900923766 /* Extensions */,
);
path = ViewController;
......@@ -317,6 +346,23 @@
path = Buttons;
sourceTree = "<group>";
};
3DD5F38325F85FDA00923766 /* Delegates */ = {
isa = PBXGroup;
children = (
3DD5F38525F85FEE00923766 /* MKMapViewDelegate+ViewController.swift */,
3DD5F3A225F8609300923766 /* ModelDelegate+ViewController.swift */,
);
path = Delegates;
sourceTree = "<group>";
};
3DD5F39625F8603000923766 /* LocationManager */ = {
isa = PBXGroup;
children = (
3DD5F39725F8603600923766 /* LocationManager.swift */,
);
path = LocationManager;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
......@@ -449,15 +495,21 @@
buildActionMask = 2147483647;
files = (
3DD5F30425F8590700923766 /* PinMarkerView.swift in Sources */,
3DD5F38625F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */,
3DD5F2ED25F8585D00923766 /* Model.swift in Sources */,
3DD5F3AD25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */,
3DD5F2F925F858B100923766 /* MapView.swift in Sources */,
3DD5F37625F85E5700923766 /* UIButton.swift in Sources */,
3DD5F39025F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */,
3DD5F33725F85B3F00923766 /* DashLine.swift in Sources */,
3DD5F35E25F85DE100923766 /* buttons+Model.swift in Sources */,
3DD5F26E25F853E900923766 /* ViewController.swift in Sources */,
3DD5F2D425F856A100923766 /* UIResponder+defaultViewController.swift in Sources */,
3DD5F3B425F8611600923766 /* MKPolyline.swift in Sources */,
3DD5F26A25F853E900923766 /* AppDelegate.swift in Sources */,
3DD5F36F25F85E1E00923766 /* action+Model.swift in Sources */,
3DD5F3A325F8609300923766 /* ModelDelegate+ViewController.swift in Sources */,
3DD5F39825F8603600923766 /* LocationManager.swift in Sources */,
3DD5F36825F85DFB00923766 /* UIEdgeInsets.swift in Sources */,
3DD5F26C25F853E900923766 /* SceneDelegate.swift in Sources */,
3DD5F35325F85D3B00923766 /* trackerButton+Model.swift in Sources */,
......@@ -473,17 +525,23 @@
buildActionMask = 2147483647;
files = (
3DD5F30525F8590700923766 /* PinMarkerView.swift in Sources */,
3DD5F39125F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */,
3DD5F33825F85B3F00923766 /* DashLine.swift in Sources */,
3DD5F36925F85DFB00923766 /* UIEdgeInsets.swift in Sources */,
3DD5F37025F85E1E00923766 /* action+Model.swift in Sources */,
3DD5F2EE25F8585D00923766 /* Model.swift in Sources */,
3DD5F2FA25F858B100923766 /* MapView.swift in Sources */,
3DD5F32325F85A7100923766 /* MKMarkerAnnotationView.swift in Sources */,
3DD5F39925F8603600923766 /* LocationManager.swift in Sources */,
3DD5F38725F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */,
3DD5F28125F853EB00923766 /* SZRCAITests.swift in Sources */,
3DD5F35F25F85DE100923766 /* buttons+Model.swift in Sources */,
3DD5F37E25F85F0400923766 /* clearButtonSetup+Model.swift in Sources */,
3DD5F3AE25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */,
3DD5F35425F85D3B00923766 /* trackerButton+Model.swift in Sources */,
3DD5F3A425F8609300923766 /* ModelDelegate+ViewController.swift in Sources */,
3DD5F2D525F856A100923766 /* UIResponder+defaultViewController.swift in Sources */,
3DD5F3B525F8611600923766 /* MKPolyline.swift in Sources */,
3DD5F37725F85E5700923766 /* UIButton.swift in Sources */,
3DD5F34725F85CAB00923766 /* buttonsSetup+ViewController.swift in Sources */,
3DD5F32E25F85B2000923766 /* PinAnnotation.swift in Sources */,
......@@ -495,17 +553,23 @@
buildActionMask = 2147483647;
files = (
3DD5F30625F8590700923766 /* PinMarkerView.swift in Sources */,
3DD5F39225F8601600923766 /* alertAuthorizedWhenInUse.swift in Sources */,
3DD5F33925F85B3F00923766 /* DashLine.swift in Sources */,
3DD5F36A25F85DFB00923766 /* UIEdgeInsets.swift in Sources */,
3DD5F37125F85E1E00923766 /* action+Model.swift in Sources */,
3DD5F2EF25F8585D00923766 /* Model.swift in Sources */,
3DD5F2FB25F858B100923766 /* MapView.swift in Sources */,
3DD5F32425F85A7100923766 /* MKMarkerAnnotationView.swift in Sources */,
3DD5F39A25F8603600923766 /* LocationManager.swift in Sources */,
3DD5F38825F85FEE00923766 /* MKMapViewDelegate+ViewController.swift in Sources */,
3DD5F28C25F853EB00923766 /* SZRCAIUITests.swift in Sources */,
3DD5F36025F85DE100923766 /* buttons+Model.swift in Sources */,
3DD5F37F25F85F0400923766 /* clearButtonSetup+Model.swift in Sources */,
3DD5F3AF25F860ED00923766 /* CLLocationCoordinate2D.swift in Sources */,
3DD5F35525F85D3B00923766 /* trackerButton+Model.swift in Sources */,
3DD5F3A525F8609300923766 /* ModelDelegate+ViewController.swift in Sources */,
3DD5F2D625F856A100923766 /* UIResponder+defaultViewController.swift in Sources */,
3DD5F3B625F8611600923766 /* MKPolyline.swift in Sources */,
3DD5F37825F85E5700923766 /* UIButton.swift in Sources */,
3DD5F34825F85CAB00923766 /* buttonsSetup+ViewController.swift in Sources */,
3DD5F32F25F85B2000923766 /* PinAnnotation.swift in Sources */,
......
import Foundation
import UIKit
import MapKit
extension ViewController: MKMapViewDelegate {
//MARK: - MKOverlayRenderer
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
switch overlay {
case let dashline as DashLine:
let renderer = MKPolylineRenderer(polyline: dashline)
renderer.strokeColor = #colorLiteral(red: 0.2470588237, green: 0.3882353008, blue: 0.5450980663, alpha: 0.685907326)
renderer.lineWidth = 5
renderer.lineDashPattern = [0, 10]
return renderer
case is MKPolyline:
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .systemRed
renderer.lineWidth = 5
return renderer
default:
return .init()
}
}
//MARK: - MKUserTrackingMode
func mapView(_ mapView: MKMapView, didChange mode: MKUserTrackingMode, animated: Bool) {
if lm.shared.status != .authorizedWhenInUse {
let alert = alertAuthorizedWhenInUse()
present(alert, animated: true, completion: {
mapView.userTrackingMode = .none
})
}
}
//MARK: - Did select annotation view
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
guard let annotation = view.annotation else { return }
mapView.deselectAnnotation(annotation, animated: true)
Model.shared.selected = nil
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotation = view.annotation else { return }
if let pin = annotation as? PinAnnotation {
mapView.selectAnnotation(pin, animated: true)
// If the graph is built, give the opportunity to choose the starting and ending point
if Model.shared.graphsBuilt { Model.shared.selected = pin }
}
}
//MARK: - MKAnnotationView constructor
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
switch annotation {
case let pin as PinAnnotation:
let id = PinMarkerView.reuseId
let view = mapView.dequeueReusableAnnotationView(withIdentifier: id, for: pin)
Model.shared.pins.append(pin)
return view
default:
return nil
}
}
//MARK: - calloutAccessoryControlTapped -
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
switch view.annotation {
case let pin as PinAnnotation:
guard let annotation = view.annotation else { return }
Model.shared.pins.removeAll(where: { $0 == pin })
Model.shared.route.removeAll(where: { $0 == pin })
mapView.removeAnnotation(annotation)
// After removing the marker, the graphs will be rebuilt
self.constructGraphs()
default: break
}
}
}
import Foundation
import UIKit
import CoreLocation
extension ViewController: ModelDelegate {
func deselectPin(pin: PinAnnotation) {
}
func modelButtonExecute(sender: UIButton) {
}
internal func constructGraphs() {
mapView.removeOverlays(mapView.overlays)
let pins = mapView.annotations.filter({ $0.isKind(of: PinAnnotation.self) })
let coords = pins.compactMap({ $0.coordinate })
coords.forEach({ (start: CLLocationCoordinate2D) in
let vertices = coords.filter({ $0 != start }) // getting all vertices excluding the starting point
vertices.forEach({ (end: CLLocationCoordinate2D) in // enumeration of all vertices
let locations = [start, end] // start and end vertices
// MARK: вершины соединены ребрами при условии, что расстояние между вершинами не более 5км
// condition: vertices are connected by edges, provided that the distance between the vertices is no more than 5 km
print("distance", locations.distance)
if locations.distance < 5000 {
let dashline = DashLine(locations: locations)
// you can also delegate the storage of all vertices and graphs
// to into a separate class in which can their compare for find matches
let exists = mapView.overlays.contains(where: { $0.coordinate == dashline.coordinate })
guard !exists else { return }
// creating a graph between vertices
mapView?.addOverlay(dashline)
if !mapView.model.graphsBuilt { mapView.model.graphsBuilt = true }
#if DEBUG
print("graphs count:", mapView.overlays.count)
#endif
} else {
let alert = UIAlertController(title: "Point is too far away!",
message: "The distance between the vertices should not be more than 5 km.",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "ОК", style: .cancel))
present(alert, animated: true)
}
})
})
}
}
......@@ -3,15 +3,8 @@ import MapKit
// Тестовое задание «СЗ РЦАИ» iOS Developer
class ViewController: UIViewController, MKMapViewDelegate, ModelDelegate {
func deselectPin(pin: PinAnnotation) {
}
func modelButtonExecute(sender: UIButton) {
}
class ViewController: UIViewController {
var mapView: MapView!
/// Button for building graphs and routes
......
import Foundation
import CoreLocation
extension CLLocationCoordinate2D: Equatable {
public var location: CLLocation {
return CLLocation(latitude: latitude, longitude: longitude)
}
public static func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
return (lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude)
}
public static func !=(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
return !(lhs == rhs)
}
}
extension Array where Element == CLLocationCoordinate2D {
/// - Tag: Distance
public var distance: CLLocationDistance {
guard let first = first, let last = last else { return 0 }
return first.location.distance(from: last.location)
}
}
import Foundation
import MapKit.MKPolyline
extension MKPolyline {
convenience init(locations: [CLLocationCoordinate2D]) {
self.init(coordinates: locations, count: locations.count)
}
}
import UIKit
func alertAuthorizedWhenInUse() -> UIAlertController {
let alert = UIAlertController(title: "You have banned location tracking", message: "To resume tracking location, grant the app access to geolocation in your iPhone settings\n(Privacy > Location Services)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .cancel))
alert.addAction(UIAlertAction(title: "Settings", style: .default, handler: { _ in
let settings = UIApplication.openSettingsURLString
if let id = Bundle.main.bundleIdentifier,
let url = URL(string: "\(settings)&path=LOCATION/\(id)") {
UIApplication.shared.open(url)
}
}))
return alert
}
import Foundation
import CoreLocation
typealias lm = LocationManager
@objc class LocationManager: CLLocationManager {
public static let shared = LocationManager()
var status: CLAuthorizationStatus! = .denied
func authorization() {
if status != .authorizedWhenInUse {
requestWhenInUseAuthorization()
} else {
startUpdatingLocation()
}
}
fileprivate override init() {
super.init()
authorization()
delegate = self
desiredAccuracy = kCLLocationAccuracyBest
distanceFilter = kCLDistanceFilterNone
}
}
extension LocationManager: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
self.status = status
switch status {
case .authorized, .authorizedWhenInUse, .authorizedAlways:
print("Access")
manager.startUpdatingLocation()
case .notDetermined, .restricted, .denied:
print("No access")
manager.requestWhenInUseAuthorization()
@unknown default:
fatalError()
}
}
}
......@@ -2,6 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>For the app to work correctly, it needs access to your location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>For the app to work correctly, it needs access to your location</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>For the app to work correctly, it needs access to your location</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment