From ed0e2a444bc1eb0b240b781d849e9f4b468939cb Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Sun, 11 Apr 2021 13:40:31 +0300 Subject: [PATCH] Revorking number checking code --- AutoCat.xcodeproj/project.pbxproj | 18 +-- .../xcdebugger/Breakpoints_v2.xcbkptlist | 16 ++ AutoCat/Base.lproj/Main.storyboard | 5 - AutoCat/Controllers/CheckController.swift | 150 ++++++++++-------- AutoCat/Extensions/CocoaError.swift | 8 +- AutoCat/Utils/Location.swift | 19 ++- 6 files changed, 122 insertions(+), 94 deletions(-) diff --git a/AutoCat.xcodeproj/project.pbxproj b/AutoCat.xcodeproj/project.pbxproj index ab000b8..95d5ddc 100644 --- a/AutoCat.xcodeproj/project.pbxproj +++ b/AutoCat.xcodeproj/project.pbxproj @@ -327,20 +327,20 @@ 7A11471423FDEAF800B424AF /* Controllers */ = { isa = PBXGroup; children = ( - 7A0420AF2561A0C100034941 /* Osago */, 7A813DC7250B5C6E00CC93B9 /* Location */, - 7A11471523FDEB2A00B424AF /* MainSplitController.swift */, - 7A11471723FDEBFA00B424AF /* ReportController.swift */, + 7A0420AF2561A0C100034941 /* Osago */, + 7A2DE69A25869ABD00A113FC /* AdsController.swift */, 7A11471923FE839000B424AF /* AuthController.swift */, 7A530B7924001D3300CBFE6E /* CheckController.swift */, - 7AEFE727240455E200910EB7 /* SettingsController.swift */, - 7A3F07AC2436350B00E59687 /* SearchController.swift */, - 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */, - 7A6E03272485951700DB22ED /* OwnersController.swift */, 7A33381024990DAE00D878F1 /* FiltersController.swift */, - 7A27ADC6249D43210035F39E /* RegionsController.swift */, + 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */, + 7A11471523FDEB2A00B424AF /* MainSplitController.swift */, + 7A6E03272485951700DB22ED /* OwnersController.swift */, 7A27ADF2249F8B650035F39E /* RecordsController.swift */, - 7A2DE69A25869ABD00A113FC /* AdsController.swift */, + 7A27ADC6249D43210035F39E /* RegionsController.swift */, + 7A11471723FDEBFA00B424AF /* ReportController.swift */, + 7A3F07AC2436350B00E59687 /* SearchController.swift */, + 7AEFE727240455E200910EB7 /* SettingsController.swift */, ); path = Controllers; sourceTree = ""; diff --git a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 618c809..483bee5 100644 --- a/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/AutoCat.xcodeproj/xcuserdata/selim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -63,5 +63,21 @@ landmarkType = "7"> + + + + diff --git a/AutoCat/Base.lproj/Main.storyboard b/AutoCat/Base.lproj/Main.storyboard index 434427a..cc2746c 100644 --- a/AutoCat/Base.lproj/Main.storyboard +++ b/AutoCat/Base.lproj/Main.storyboard @@ -855,7 +855,6 @@ - @@ -874,7 +873,6 @@ - @@ -892,7 +890,6 @@ - @@ -911,7 +908,6 @@ - @@ -929,7 +925,6 @@ - diff --git a/AutoCat/Controllers/CheckController.swift b/AutoCat/Controllers/CheckController.swift index bfe5ab4..9c6c1b9 100644 --- a/AutoCat/Controllers/CheckController.swift +++ b/AutoCat/Controllers/CheckController.swift @@ -6,7 +6,7 @@ import RxRealm import PKHUD import CoreLocation -enum EventAction { +enum EventAction: Equatable { case doNotSend case receiveAndSend case sendSpecific(VehicleEvent) @@ -94,9 +94,12 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat action = .sendSpecific(event) } HUD.show(.progress) - self.check(number: number, action: action).subscribe { vehicle in - self.updateDetailController(with: vehicle) + self.check(number: number, action: action).subscribe { (vehicle, errors) in + if !vehicle.unrecognized { + self.updateDetailController(with: vehicle) + } HUD.hide() + self.showErrors(errors) } onError: { error in HUD.hide() self.show(error: error) @@ -210,18 +213,15 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat self.check.isEnabled = false HUD.show(.progress) - self.check(number: numberNormalized, action: .receiveAndSend).subscribe { vehicle in - self.updateDetailController(with: vehicle) + self.check(number: numberNormalized, action: .receiveAndSend).subscribe { (vehicle, errors) in + if !vehicle.unrecognized { + self.updateDetailController(with: vehicle) + } HUD.hide() + self.showErrors(errors) } onError: { error in HUD.hide() - 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) - } + self.show(error: error) } .disposed(by: self.bag) @@ -251,7 +251,6 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat // MARK: - UITextFieldDelegate @IBAction func textFieldDidBeginEditing(_ textField: UITextField) { - print("+++ textFieldDidBeginEditing, requesting new location") LocationManager.requestCurrentLocation().subscribe().disposed(by: self.bag) } @@ -323,13 +322,15 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat eventAction = .sendSpecific(savedEvent) } - self.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { vehicle in - self.updateDetailController(with: vehicle) + self.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { (vehicle, errors) in + if !vehicle.unrecognized { + self.updateDetailController(with: vehicle) + } HUD.hide() + self.showErrors(errors) } onError: { error in HUD.hide() self.show(error: error) - //HUD.show(error: error) } .disposed(by: self.bag) } @@ -362,77 +363,88 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat } 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)") + func check(number: String, action: EventAction, force: Bool = false) -> Single<(vehicle: Vehicle, errors: [Error])> { + var eventSingle: Single<(event: VehicleEvent?, error: Error?)> = .just((event: nil, error: nil)) + if action != .doNotSend { + eventSingle = self.getEvent(for: action) + .flatMap { event in event.findAddress().map{ event }.catchErrorJustReturn(event) } + .map { event -> (event: VehicleEvent?, error: Error?) in (event: event, error: nil) } + .observeOn(MainScheduler.instance) + .catchError { .just((event: nil, error: $0)) } + } + let checkSingle = Api.checkVehicle(by: number, force: force) .observeOn(MainScheduler.instance) - .map { (vehicle: Vehicle) -> Vehicle in + .map { (vehicle: Vehicle) -> (vehicle: Vehicle, error: Error?) in try self.save(vehicle: vehicle) - print("+++ Vehicle saved") - return vehicle + return (vehicle: vehicle, error: nil) } - .do (onError: { err in + .catchError { error in let realm = try Realm() - if realm.object(ofType: Vehicle.self, forPrimaryKey: number) == nil { + if let existingVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: number) { + return .just((vehicle: existingVehicle, error: error)) + } else { let vehicle = Vehicle(number) try realm.write { realm.add(vehicle, update: .all) } - - self.getEvent(for: action) - //.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 { event in - try realm.write { vehicle.events.append(event) } - print("+++ event added") - } - .subscribe() - .disposed(by: self.bag) + return .just((vehicle: vehicle, error: error)) } - }) - + } + + return Single.zip(eventSingle, checkSingle).flatMap { eventResult, vehicleResult in + let errors = [eventResult.error, vehicleResult.error].map { error -> Error? in + if let clerror = error as? CLError { + if clerror.code != .denied { + return CocoaError.error(NSLocalizedString("Location error", comment: ""), reason: clerror.code.description) + } else { + return nil + } + } else { + return error + } + } + .compactMap { $0 } - if case .doNotSend = action { - return checkSingle - } else { - return checkSingle - .flatMap { self.addEvent(to: $0, action: action) } - } - } - - func addEvent(to vehicle: Vehicle, action: EventAction) -> Single { - return self.getEvent(for: action).flatMap { event in - return event - .findAddress() - .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 + LocationManager.resetLastEvent() + + if vehicleResult.vehicle.unrecognized { + let realm = try Realm() + if let event = eventResult.event { + try realm.write { vehicleResult.vehicle.events.append(event) } } - //.catchErrorJustReturn(vehicle) + return .just((vehicle: vehicleResult.vehicle, errors: errors)) + } else { + if let event = eventResult.event { + return Api.add(event: event, to: vehicleResult.vehicle.getNumber()) + .observeOn(MainScheduler.instance) + .map { + try self.save(vehicle: $0) + return (vehicle: $0, errors: errors) + } + } else { + return .just((vehicle: vehicleResult.vehicle, errors: errors)) + } + } } - //.catchErrorJustReturn(vehicle) } - deinit { - print("+++ CheckController deinit") + func showErrors(_ errors: [Error]) { + let observables = errors.map(rxShowError) + Observable.from(observables).concat().subscribe().disposed(by: self.bag) + } + + func rxShowError(_ error: Error) -> Observable { + return Observable.create { observer in + self.show(error: error, animated: true) { + observer.on(.next(())) + observer.on(.completed) + } + return Disposables.create() + } } } diff --git a/AutoCat/Extensions/CocoaError.swift b/AutoCat/Extensions/CocoaError.swift index e483939..2edcf5e 100644 --- a/AutoCat/Extensions/CocoaError.swift +++ b/AutoCat/Extensions/CocoaError.swift @@ -38,11 +38,13 @@ extension CocoaError { } extension UIViewController { - func show(error: Error) { + func show(error: Error, animated: Bool = true, completion: (() -> Void)? = nil) { let msg = (error as NSError).displayMessage let alert = UIAlertController(title: msg.title, message: msg.body, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) - self.present(alert, animated: true) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in + completion?() + })) + self.present(alert, animated: animated) } func showAlert(title: String, message: String) { diff --git a/AutoCat/Utils/Location.swift b/AutoCat/Utils/Location.swift index e93f0d9..baf2aca 100644 --- a/AutoCat/Utils/Location.swift +++ b/AutoCat/Utils/Location.swift @@ -36,13 +36,11 @@ 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) } } @@ -50,10 +48,8 @@ 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) { @@ -95,6 +91,9 @@ class LocationManager { observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"]))) } }, onError: { observer(.error($0)) }) + case .denied: + observer(.error(CLError(.denied))) + break default: observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"]))) break @@ -107,7 +106,6 @@ class LocationManager { private static func requestLocation() -> Single { let proxy = RxLocationManagerDelegateProxy.proxy(for: self.manager) 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 @@ -118,14 +116,11 @@ class LocationManager { static func requestCurrentLocation() -> Single { 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() }) @@ -133,6 +128,10 @@ class LocationManager { } } + static func locationRequestInProgress() -> Bool { + return self.eventObservable != nil + } + static func getAddressForLocation(latitude: Double, longitude: Double) -> Single { return Single.create { observer in let geocoder = CLGeocoder() @@ -152,4 +151,8 @@ class LocationManager { } } } + + static func resetLastEvent() { + self.lastEvent = nil + } }