Revorking number checking code

This commit is contained in:
Selim Mustafaev 2021-04-11 13:40:31 +03:00
parent 0a1f9d4363
commit ed0e2a444b
6 changed files with 122 additions and 94 deletions

View File

@ -327,20 +327,20 @@
7A11471423FDEAF800B424AF /* Controllers */ = { 7A11471423FDEAF800B424AF /* Controllers */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A0420AF2561A0C100034941 /* Osago */,
7A813DC7250B5C6E00CC93B9 /* Location */, 7A813DC7250B5C6E00CC93B9 /* Location */,
7A11471523FDEB2A00B424AF /* MainSplitController.swift */, 7A0420AF2561A0C100034941 /* Osago */,
7A11471723FDEBFA00B424AF /* ReportController.swift */, 7A2DE69A25869ABD00A113FC /* AdsController.swift */,
7A11471923FE839000B424AF /* AuthController.swift */, 7A11471923FE839000B424AF /* AuthController.swift */,
7A530B7924001D3300CBFE6E /* CheckController.swift */, 7A530B7924001D3300CBFE6E /* CheckController.swift */,
7AEFE727240455E200910EB7 /* SettingsController.swift */,
7A3F07AC2436350B00E59687 /* SearchController.swift */,
7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */,
7A6E03272485951700DB22ED /* OwnersController.swift */,
7A33381024990DAE00D878F1 /* FiltersController.swift */, 7A33381024990DAE00D878F1 /* FiltersController.swift */,
7A27ADC6249D43210035F39E /* RegionsController.swift */, 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */,
7A11471523FDEB2A00B424AF /* MainSplitController.swift */,
7A6E03272485951700DB22ED /* OwnersController.swift */,
7A27ADF2249F8B650035F39E /* RecordsController.swift */, 7A27ADF2249F8B650035F39E /* RecordsController.swift */,
7A2DE69A25869ABD00A113FC /* AdsController.swift */, 7A27ADC6249D43210035F39E /* RegionsController.swift */,
7A11471723FDEBFA00B424AF /* ReportController.swift */,
7A3F07AC2436350B00E59687 /* SearchController.swift */,
7AEFE727240455E200910EB7 /* SettingsController.swift */,
); );
path = Controllers; path = Controllers;
sourceTree = "<group>"; sourceTree = "<group>";

View File

@ -63,5 +63,21 @@
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "A2917113-DA52-4374-ADE1-6BB476EC9BD9"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "401"
endingLineNumber = "401"
landmarkName = "check(number:action:force:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints> </Breakpoints>
</Bucket> </Bucket>

View File

@ -855,7 +855,6 @@
<tabBarItem key="tabBarItem" title="Check" image="check" landscapeImage="check-compact" id="QJd-35-4OB"/> <tabBarItem key="tabBarItem" title="Check" image="check" landscapeImage="check-compact" id="QJd-35-4OB"/>
<toolbarItems/> <toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="AAc-4d-GNh"> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="AAc-4d-GNh">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<nil name="viewControllers"/> <nil name="viewControllers"/>
@ -874,7 +873,6 @@
<tabBarItem key="tabBarItem" title="Search" image="search" landscapeImage="search-compact" id="gDG-z8-R0t"/> <tabBarItem key="tabBarItem" title="Search" image="search" landscapeImage="search-compact" id="gDG-z8-R0t"/>
<toolbarItems/> <toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="vdY-9n-hjX"> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="vdY-9n-hjX">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<nil name="viewControllers"/> <nil name="viewControllers"/>
@ -892,7 +890,6 @@
<navigationController storyboardIdentifier="ReportNavController" automaticallyAdjustsScrollViewInsets="NO" id="Km4-b6-SGW" sceneMemberID="viewController"> <navigationController storyboardIdentifier="ReportNavController" automaticallyAdjustsScrollViewInsets="NO" id="Km4-b6-SGW" sceneMemberID="viewController">
<toolbarItems/> <toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="JaO-tp-k6N"> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="JaO-tp-k6N">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<nil name="viewControllers"/> <nil name="viewControllers"/>
@ -911,7 +908,6 @@
<tabBarItem key="tabBarItem" title="Records" image="record" landscapeImage="record-compact" id="lxF-EY-z8V"/> <tabBarItem key="tabBarItem" title="Records" image="record" landscapeImage="record-compact" id="lxF-EY-z8V"/>
<toolbarItems/> <toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="8YG-pw-LE7"> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="8YG-pw-LE7">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<nil name="viewControllers"/> <nil name="viewControllers"/>
@ -929,7 +925,6 @@
<navigationController storyboardIdentifier="GlobalEventsNavigation" automaticallyAdjustsScrollViewInsets="NO" id="HWa-Ea-ZKD" sceneMemberID="viewController"> <navigationController storyboardIdentifier="GlobalEventsNavigation" automaticallyAdjustsScrollViewInsets="NO" id="HWa-Ea-ZKD" sceneMemberID="viewController">
<toolbarItems/> <toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="REm-5j-xeL"> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="REm-5j-xeL">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
</navigationBar> </navigationBar>
<nil name="viewControllers"/> <nil name="viewControllers"/>

View File

@ -6,7 +6,7 @@ import RxRealm
import PKHUD import PKHUD
import CoreLocation import CoreLocation
enum EventAction { enum EventAction: Equatable {
case doNotSend case doNotSend
case receiveAndSend case receiveAndSend
case sendSpecific(VehicleEvent) case sendSpecific(VehicleEvent)
@ -94,9 +94,12 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
action = .sendSpecific(event) action = .sendSpecific(event)
} }
HUD.show(.progress) HUD.show(.progress)
self.check(number: number, action: action).subscribe { vehicle in self.check(number: number, action: action).subscribe { (vehicle, errors) in
self.updateDetailController(with: vehicle) if !vehicle.unrecognized {
self.updateDetailController(with: vehicle)
}
HUD.hide() HUD.hide()
self.showErrors(errors)
} onError: { error in } onError: { error in
HUD.hide() HUD.hide()
self.show(error: error) self.show(error: error)
@ -210,18 +213,15 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
self.check.isEnabled = false self.check.isEnabled = false
HUD.show(.progress) HUD.show(.progress)
self.check(number: numberNormalized, action: .receiveAndSend).subscribe { vehicle in self.check(number: numberNormalized, action: .receiveAndSend).subscribe { (vehicle, errors) in
self.updateDetailController(with: vehicle) if !vehicle.unrecognized {
self.updateDetailController(with: vehicle)
}
HUD.hide() HUD.hide()
self.showErrors(errors)
} onError: { error in } onError: { error in
HUD.hide() HUD.hide()
if let clerror = error as? CLError { self.show(error: error)
if clerror.code != .denied {
self.showAlert(title: NSLocalizedString("Location error", comment: ""), message: clerror.code.description)
}
} else {
self.show(error: error)
}
} }
.disposed(by: self.bag) .disposed(by: self.bag)
@ -251,7 +251,6 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
// MARK: - UITextFieldDelegate // MARK: - UITextFieldDelegate
@IBAction func textFieldDidBeginEditing(_ textField: UITextField) { @IBAction func textFieldDidBeginEditing(_ textField: UITextField) {
print("+++ textFieldDidBeginEditing, requesting new location")
LocationManager.requestCurrentLocation().subscribe().disposed(by: self.bag) LocationManager.requestCurrentLocation().subscribe().disposed(by: self.bag)
} }
@ -323,13 +322,15 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
eventAction = .sendSpecific(savedEvent) eventAction = .sendSpecific(savedEvent)
} }
self.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { vehicle in self.check(number: vehicle.getNumber(), action: eventAction, force: true).subscribe { (vehicle, errors) in
self.updateDetailController(with: vehicle) if !vehicle.unrecognized {
self.updateDetailController(with: vehicle)
}
HUD.hide() HUD.hide()
self.showErrors(errors)
} onError: { error in } onError: { error in
HUD.hide() HUD.hide()
self.show(error: error) self.show(error: error)
//HUD.show(error: error)
} }
.disposed(by: self.bag) .disposed(by: self.bag)
} }
@ -362,77 +363,88 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
} }
if let event = LocationManager.lastEvent, (Date().timeIntervalSince1970 - event.date) < 100 { if let event = LocationManager.lastEvent, (Date().timeIntervalSince1970 - event.date) < 100 {
print("+++ getEvent, using last event")
return Single<VehicleEvent>.just(event) return Single<VehicleEvent>.just(event)
} else { } else {
print("+++ getEvent, requesting new location")
return LocationManager.requestCurrentLocation() return LocationManager.requestCurrentLocation()
} }
} }
func check(number: String, action: EventAction, force: Bool = false) -> Single<Vehicle> { func check(number: String, action: EventAction, force: Bool = false) -> Single<(vehicle: Vehicle, errors: [Error])> {
print("+++ Checking numnber, event: \(action)") 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) let checkSingle = Api.checkVehicle(by: number, force: force)
.observeOn(MainScheduler.instance) .observeOn(MainScheduler.instance)
.map { (vehicle: Vehicle) -> Vehicle in .map { (vehicle: Vehicle) -> (vehicle: Vehicle, error: Error?) in
try self.save(vehicle: vehicle) try self.save(vehicle: vehicle)
print("+++ Vehicle saved") return (vehicle: vehicle, error: nil)
return vehicle
} }
.do (onError: { err in .catchError { error in
let realm = try Realm() 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) let vehicle = Vehicle(number)
try realm.write { realm.add(vehicle, update: .all) } try realm.write { realm.add(vehicle, update: .all) }
return .just((vehicle: vehicle, error: error))
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 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 { LocationManager.resetLastEvent()
return checkSingle
} else { if vehicleResult.vehicle.unrecognized {
return checkSingle let realm = try Realm()
.flatMap { self.addEvent(to: $0, action: action) } if let event = eventResult.event {
} try realm.write { vehicleResult.vehicle.events.append(event) }
}
func addEvent(to vehicle: Vehicle, action: EventAction) -> Single<Vehicle> {
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
} }
//.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 { func showErrors(_ errors: [Error]) {
print("+++ CheckController deinit") let observables = errors.map(rxShowError)
Observable.from(observables).concat().subscribe().disposed(by: self.bag)
}
func rxShowError(_ error: Error) -> Observable<Void> {
return Observable<Void>.create { observer in
self.show(error: error, animated: true) {
observer.on(.next(()))
observer.on(.completed)
}
return Disposables.create()
}
} }
} }

View File

@ -38,11 +38,13 @@ extension CocoaError {
} }
extension UIViewController { extension UIViewController {
func show(error: Error) { func show(error: Error, animated: Bool = true, completion: (() -> Void)? = nil) {
let msg = (error as NSError).displayMessage let msg = (error as NSError).displayMessage
let alert = UIAlertController(title: msg.title, message: msg.body, preferredStyle: .alert) let alert = UIAlertController(title: msg.title, message: msg.body, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
self.present(alert, animated: true) completion?()
}))
self.present(alert, animated: animated)
} }
func showAlert(title: String, message: String) { func showAlert(title: String, message: String) {

View File

@ -36,13 +36,11 @@ class RxLocationManagerDelegateProxy: DelegateProxy<CLLocationManager, CLLocatio
// MARK: - CLLocationManagerDelegate // MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print("+++ >>> locationManager didChangeAuthorization")
self.authSubject.onNext(status) self.authSubject.onNext(status)
} }
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first { if let location = locations.first {
print("+++ >>> locationManager didUpdateLocations")
self.locationSubject.onNext(location) self.locationSubject.onNext(location)
} }
} }
@ -50,10 +48,8 @@ class RxLocationManagerDelegateProxy: DelegateProxy<CLLocationManager, CLLocatio
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
guard let err = error as? CLError else { return } guard let err = error as? CLError else { return }
print("+++ >>> locationManager didFailWithError: \(error)")
if self.generalErrors.contains(err.code) { if self.generalErrors.contains(err.code) {
// Pass general errors to all existing subjects // Pass general errors to all existing subjects
print("+++ >>> passing error to subjects, code: \(err.code)")
self.authSubject.onError(error) self.authSubject.onError(error)
self.locationSubject.onError(error) self.locationSubject.onError(error)
} else if self.geocodingErrors.contains(err.code) { } else if self.geocodingErrors.contains(err.code) {
@ -95,6 +91,9 @@ class LocationManager {
observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"]))) observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"])))
} }
}, onError: { observer(.error($0)) }) }, onError: { observer(.error($0)) })
case .denied:
observer(.error(CLError(.denied)))
break
default: default:
observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"]))) observer(.error(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Location permission error"])))
break break
@ -107,7 +106,6 @@ class LocationManager {
private static func requestLocation() -> Single<VehicleEvent> { private static func requestLocation() -> Single<VehicleEvent> {
let proxy = RxLocationManagerDelegateProxy.proxy(for: self.manager) let proxy = RxLocationManagerDelegateProxy.proxy(for: self.manager)
let single = proxy.getNewLocationSubject().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) let event = VehicleEvent(lat: location.coordinate.latitude, lon: location.coordinate.longitude, speed: location.speed, dir: location.course)
self.lastEvent = event self.lastEvent = event
return event return event
@ -118,14 +116,11 @@ class LocationManager {
static func requestCurrentLocation() -> Single<VehicleEvent> { static func requestCurrentLocation() -> Single<VehicleEvent> {
if let result = self.eventObservable { if let result = self.eventObservable {
print("+++ >>> requestCurrentLocation existing")
return result return result
} else { } else {
print("+++ >>> requestCurrentLocation new")
self.eventObservable = self.checkPermissions().flatMap(self.requestLocation).do(onError: { _ in self.eventObservable = self.checkPermissions().flatMap(self.requestLocation).do(onError: { _ in
self.eventObservable = nil self.eventObservable = nil
}, onDispose: { }, onDispose: {
print("+++ >>> stopUpdatingLocation")
self.eventObservable = nil self.eventObservable = nil
self.manager.stopUpdatingLocation() 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<String> { static func getAddressForLocation(latitude: Double, longitude: Double) -> Single<String> {
return Single.create { observer in return Single.create { observer in
let geocoder = CLGeocoder() let geocoder = CLGeocoder()
@ -152,4 +151,8 @@ class LocationManager {
} }
} }
} }
static func resetLastEvent() {
self.lastEvent = nil
}
} }