diff --git a/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 099e37a..4a8dc44 100644 --- a/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/AutoCat.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/onevcat/Kingfisher", "state": { "branch": null, - "revision": "2a10bf41da75599a9f8e872dbd44fe0155a2e00c", - "version": "5.15.8" + "revision": "2a6d1135af3915547c4b08c3b154a05e6f1075a3", + "version": "5.15.5" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/realm/realm-cocoa", "state": { "branch": null, - "revision": "7ec5df0a700ef76ad930dcedb9c63c1b354979e1", - "version": "5.5.1" + "revision": "2dc2d259095051b997b76a07e859822661105303", + "version": "5.4.7" } }, { @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/realm/realm-core", "state": { "branch": null, - "revision": "66d79b3c5213fb14d491c1b22193077b488d49a6", - "version": "6.2.4" + "revision": "2df510904ad04287926b287b4e89b786de2808c8", + "version": "6.1.3" } }, { @@ -78,8 +78,8 @@ "repositoryURL": "https://github.com/ReactiveX/RxSwift.git", "state": { "branch": null, - "revision": "254617dd7fae0c45319ba5fbea435bf4d0e15b5d", - "version": "5.1.2" + "revision": "002d325b0bdee94e7882e1114af5ff4fe1e96afa", + "version": "5.1.1" } }, { @@ -87,8 +87,8 @@ "repositoryURL": "https://github.com/malcommac/SwiftDate.git", "state": { "branch": null, - "revision": "6190d0cefff3013e77ed567e6b074f324e5c5bf5", - "version": "6.3.1" + "revision": "a25913b19833860b61fac161a706e44834f03c47", + "version": "6.2.0" } } ] diff --git a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 7ea2458..618c809 100644 --- a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -63,149 +63,5 @@ landmarkType = "7"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutoCat/Controllers/CheckController.swift b/AutoCat/Controllers/CheckController.swift index 978ec80..bfe5ab4 100644 --- a/AutoCat/Controllers/CheckController.swift +++ b/AutoCat/Controllers/CheckController.swift @@ -4,6 +4,7 @@ import RxSwift import SwiftDate import RxRealm import PKHUD +import CoreLocation enum EventAction { case doNotSend @@ -17,6 +18,16 @@ enum HistoryFilter { case outdated } +extension String.StringInterpolation { + mutating func appendInterpolation(_ value: EventAction) { + switch value { + case .doNotSend: appendLiteral("do not send"); break + case .receiveAndSend: appendLiteral("receive and send"); break + case .sendSpecific(let event): appendLiteral("send specific (\(event.latitude), \(event.longitude)"); break + } + } +} + class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegate, PNKeyboardDelegate { @IBOutlet weak var number: SwiftMaskTextfield! @@ -204,8 +215,13 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat HUD.hide() } onError: { error in HUD.hide() - self.show(error: error) - //HUD.show(error: error) + if let clerror = error as? CLError { + if clerror.code != .denied { + self.showAlert(title: NSLocalizedString("Location error", comment: ""), message: clerror.code.description) + } + } else { + self.show(error: error) + } } .disposed(by: self.bag) @@ -235,6 +251,7 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat // MARK: - UITextFieldDelegate @IBAction func textFieldDidBeginEditing(_ textField: UITextField) { + print("+++ textFieldDidBeginEditing, requesting new location") LocationManager.requestCurrentLocation().subscribe().disposed(by: self.bag) } @@ -344,18 +361,22 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat return Single.just(event) } - if let event = LocationManager.lastEvent, (Date().timeIntervalSince1970 - event.date) < 15 { + if let event = LocationManager.lastEvent, (Date().timeIntervalSince1970 - event.date) < 100 { + print("+++ getEvent, using last event") return Single.just(event) } else { + print("+++ getEvent, requesting new location") return LocationManager.requestCurrentLocation() } } func check(number: String, action: EventAction, force: Bool = false) -> Single { + print("+++ Checking numnber, event: \(action)") let checkSingle = Api.checkVehicle(by: number, force: force) .observeOn(MainScheduler.instance) .map { (vehicle: Vehicle) -> Vehicle in try self.save(vehicle: vehicle) + print("+++ Vehicle saved") return vehicle } .do (onError: { err in @@ -365,11 +386,17 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat try realm.write { realm.add(vehicle, update: .all) } self.getEvent(for: action) - .flatMap { event in event.findAddress().map{ [event] }.catchErrorJustReturn([event]) } + //.flatMap { event in event.findAddress().map{ [event] }.catchErrorJustReturn([event]) } + .do(onError: { error in + print("+++ error getting event: \(error)") + }, onDispose: { + print("+++ Dispose") + }) .observeOn(MainScheduler.instance) - .catchErrorJustReturn([]) - .map { events in - try realm.write { vehicle.events.append(objectsIn: events) } + //.catchErrorJustReturn([]) + .map { event in + try realm.write { vehicle.events.append(event) } + print("+++ event added") } .subscribe() .disposed(by: self.bag) @@ -392,13 +419,20 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat .map{ event } .catchErrorJustReturn(event) .flatMap { Api.add(event: $0, to: vehicle.freeze().getNumber()) } + .do(onDispose: { + print("+++ Dispose 2") + }) .observeOn(MainScheduler.instance) .map { try self.save(vehicle: $0) return $0 } - .catchErrorJustReturn(vehicle) + //.catchErrorJustReturn(vehicle) } - .catchErrorJustReturn(vehicle) + //.catchErrorJustReturn(vehicle) + } + + deinit { + print("+++ CheckController deinit") } } diff --git a/AutoCat/Extensions/CocoaError.swift b/AutoCat/Extensions/CocoaError.swift index 391ddae..e483939 100644 --- a/AutoCat/Extensions/CocoaError.swift +++ b/AutoCat/Extensions/CocoaError.swift @@ -1,5 +1,6 @@ import UIKit import PKHUD +import CoreLocation extension NSError { var displayMessage: (title: String, body: String) { @@ -57,3 +58,29 @@ extension HUD { self.flash(.labeledError(title: msg.title, subtitle: msg.body), delay: 2.0) } } + +extension CLError.Code: CustomStringConvertible { + public var description: String { + switch self { + case .locationUnknown: return "Location unknown" + case .denied: return "Access denied" + case .network: return "general, network-related error" + case .headingFailure: return "heading could not be determined" + case .regionMonitoringDenied: return "Location region monitoring has been denied" + case .regionMonitoringSetupDelayed: return "CL could not immediately initialize region monitoring" + case .regionMonitoringResponseDelayed: return "While events for this fence will be delivered, delivery will not occur immediately" + case .geocodeFoundNoResult: return "A geocode request yielded no result" + case .geocodeFoundPartialResult: return "A geocode request yielded a partial result" + case .geocodeCanceled: return "A geocode request was cancelled" + case .deferredFailed: return "Deferred mode failed" + case .deferredNotUpdatingLocation: return "Deferred mode failed because location updates disabled or paused" + case .deferredAccuracyTooLow: return "Deferred mode not supported for the requested accuracy" + case .deferredDistanceFiltered: return "Deferred mode does not support distance filters" + case .deferredCanceled: return "Deferred mode request canceled a previous request" + case .rangingUnavailable: return "Ranging cannot be performed" + case .rangingFailure: return "General ranging failure" + case .promptDeclined: return "Authorization request not presented to user" + default: return "Unknown location error (\(self.rawValue)" + } + } +} diff --git a/AutoCat/Utils/Location.swift b/AutoCat/Utils/Location.swift index 063eec0..e93f0d9 100644 --- a/AutoCat/Utils/Location.swift +++ b/AutoCat/Utils/Location.swift @@ -36,11 +36,13 @@ class RxLocationManagerDelegateProxy: DelegateProxy>> locationManager didChangeAuthorization") self.authSubject.onNext(status) } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first { + print("+++ >>> locationManager didUpdateLocations") self.locationSubject.onNext(location) } } @@ -48,8 +50,10 @@ class RxLocationManagerDelegateProxy: DelegateProxy>> locationManager didFailWithError: \(error)") if self.generalErrors.contains(err.code) { // Pass general errors to all existing subjects + print("+++ >>> passing error to subjects, code: \(err.code)") self.authSubject.onError(error) self.locationSubject.onError(error) } else if self.geocodingErrors.contains(err.code) { @@ -58,6 +62,11 @@ class RxLocationManagerDelegateProxy: DelegateProxy PublishSubject { + self.locationSubject = PublishSubject() + return self.locationSubject + } } class LocationManager { @@ -67,6 +76,7 @@ class LocationManager { return mgr }() private static let bag = DisposeBag() + private static var eventObservable: Single? private(set) static var lastEvent: VehicleEvent? private static func checkPermissions() -> Single { @@ -96,7 +106,8 @@ class LocationManager { private static func requestLocation() -> Single { let proxy = RxLocationManagerDelegateProxy.proxy(for: self.manager) - let single = proxy.locationSubject.take(1).asSingle().map { location -> VehicleEvent in + let single = proxy.getNewLocationSubject().take(1).asSingle().map { location -> VehicleEvent in + print("+++ >>> Initializing new event") let event = VehicleEvent(lat: location.coordinate.latitude, lon: location.coordinate.longitude, speed: location.speed, dir: location.course) self.lastEvent = event return event @@ -106,9 +117,20 @@ class LocationManager { } static func requestCurrentLocation() -> Single { - return self.checkPermissions().flatMap(self.requestLocation).do(onDispose: { - self.manager.stopUpdatingLocation() - }) + if let result = self.eventObservable { + print("+++ >>> requestCurrentLocation existing") + return result + } else { + print("+++ >>> requestCurrentLocation new") + self.eventObservable = self.checkPermissions().flatMap(self.requestLocation).do(onError: { _ in + self.eventObservable = nil + }, onDispose: { + print("+++ >>> stopUpdatingLocation") + self.eventObservable = nil + self.manager.stopUpdatingLocation() + }) + return self.eventObservable! + } } static func getAddressForLocation(latitude: Double, longitude: Double) -> Single {