Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduces re-vamped AppContext & general architecture #256

Merged
merged 36 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
634e8f5
good first take, plenty of bugs to work out
esreli Sep 18, 2020
65e45b9
fixes download map procedure
esreli Sep 18, 2020
00785a2
rids of unnecessary Notification
esreli Sep 18, 2020
17f8a30
makes app location a part of app context
esreli Sep 18, 2020
a154523
improves app location api
esreli Sep 18, 2020
497c456
removes unncessary AppFonts
esreli Sep 18, 2020
8a03365
removes unncessary types and files
esreli Sep 18, 2020
3770221
I believe i've fixed portal session management
esreli Sep 18, 2020
01e042a
fixes another issue where user portal was revoked
esreli Sep 18, 2020
ed36dcd
improves/unifies logging within AppContext and parts
esreli Sep 18, 2020
0901f8c
slight improvement
esreli Sep 18, 2020
c7c8f08
slight improvement
esreli Sep 18, 2020
176a1d6
reorganizes AppConfiguration
esreli Sep 18, 2020
350f524
slight more reorganization
esreli Sep 18, 2020
d0a85fc
logs app context
esreli Sep 21, 2020
cb81331
access control for WorkMode
esreli Sep 21, 2020
f89f15a
introduces loading UI for profile view controller
esreli Sep 22, 2020
0c96573
fixes preparing for a download job
esreli Sep 23, 2020
0f76408
fixes bug
esreli Sep 23, 2020
8212e74
introduces support for optionally ignoring NSUserDidCancel errors
esreli Sep 23, 2020
1b849b7
fixes edge case
esreli Sep 23, 2020
17a4e6b
reorganizes AppConfiguration
esreli Sep 23, 2020
4fa6b52
reorganizes AppConfiguration
esreli Sep 23, 2020
141df40
reorganizes AppConfiguration
esreli Sep 23, 2020
6d4001b
improves configuration
esreli Sep 24, 2020
fd14fe1
creates formal configuration types
esreli Sep 24, 2020
f5968f5
small fixes
esreli Sep 24, 2020
c8efedd
more docs
esreli Sep 25, 2020
4d71c8f
Improves AddressLocator with more sturdy AppConfiguration
esreli Sep 25, 2020
3e4f627
improves AddressLocator as member of AppContext
esreli Sep 25, 2020
883d598
updates doc with changes to architecture
esreli Sep 25, 2020
4d6c8d4
updates doc with new AppContext architecture
esreli Sep 25, 2020
9c6b02b
improves showing Alerts
esreli Sep 25, 2020
4c8300a
moves some extensions to only file they're used
esreli Sep 27, 2020
6f81677
updates access control for property
esreli Oct 1, 2020
e316a5a
changes to release notes, small docs change to AddressLocator
esreli Oct 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Release 1.3

- TODO
- Introduces an improved `AppContext` state-based architecture and more clear separation of responsibility. This architecture achieves more stability and resolves some found Portal related edge cases. Consult [docs](./docs/README.md#app-context) for more information.
- Dissolves `AppLocation` into sub-component of `AppContext`.
- Dissolves `AppGlobals` into `AppContext`.
- Dissolves `AppFiles` into `OfflineMapManager`.
- Removes `AppFonts` as it provides very little utility.
- Removes `NetworkReachabilityManager` as a first class state mechanism allowing app to determine reachability with every network request, removes `Alamofire` swift package.
- Reformats `AppConfiguration` to be more clear.
- Introduces `GlobalAlertQueue`, a utility for enqueueing and presenting alerts in a stand-alone alert window (`UIWindow`). This change improves the reliability of presenting alerts from any app component - context, view, or otherwise.

# Release 1.2.2

Expand Down
114 changes: 16 additions & 98 deletions data-collection/data-collection.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,55 @@
import Foundation
import ArcGIS

/// This class facilitates reverse geocoding, contingent on app work mode and reachability.
/// This class facilitates reverse geocoding, contingent on app work mode.
class AddressLocator {

// Online locator using the world geocoder service.
private lazy var onlineLocator = AGSLocatorTask(url: .geocodeService)
private lazy var onlineLocator = AGSLocatorTask(url: OnlineGeocoderConfig.url)

// Offline locator using the side loaded 'AddressLocator'.
private lazy var offlineLocator = AGSLocatorTask(name: .offlineLocator)
private lazy var offlineLocator = AGSLocatorTask(name: OfflineGeocoderConfig.name)

private var appContextAwareLocator: AGSLocatorTask {
// We want to use the online locator if the work mode is online and the app has reachability.
if appContext.workMode == .online && appReachability.isReachable {
return onlineLocator
init(default workMode: AppContext.WorkMode) {
prepareLocator(for: workMode)
}

func prepareLocator(for workMode: AppContext.WorkMode) {
switch workMode {
case .offline:
offlineLocator.load(completion: nil)
currentLocator = offlineLocator
case .online:
onlineLocator.load(completion: nil)
currentLocator = onlineLocator
case .none:
currentLocator = nil
}
// Otherwise, we'll use the offline locator.
else {
return offlineLocator
}

private var currentLocator: AGSLocatorTask?

// MARK: Errors

struct NoLocatorError: LocalizedError {
let localizedDescription = "No locator."
}

struct NoResultsError: LocalizedError {
let localizedDescription = "Operation yeilded no results."
}

struct MissingAttribute: LocalizedError {
let key: String
var localizedDescription: String {
String(format: "Geocode result missing value for key '%@'", key)
}
}

struct UnknownError: LocalizedError {
let localizedDescription = "An unknown error occured."
}

/// Reverse geocode an address from a map point.
///
/// - Parameters:
Expand All @@ -42,14 +72,13 @@ class AddressLocator {
/// - result: The result of the reverse geocode operation, with either the
/// address or an error.
func reverseGeocodeAddress(for point: AGSPoint, completion: @escaping (_ result: Result<String, Error>) -> Void) {
let locator = appContextAwareLocator

guard let locator = currentLocator else {
completion(.failure(NoLocatorError()))
return
}

locator.load { [weak self] (error) in
// Ensure the loaded locator matches the app context aware locator.
// The app context might have changed since the locator started loading.
guard locator == self?.appContextAwareLocator else {
completion(.failure(NSError.unknown))
return
}
// If the locator load failed, end early.
if let error = error {
completion(.failure(error))
Expand All @@ -65,16 +94,30 @@ class AddressLocator {
}()
// Perform the reverse geocode task.
locator.reverseGeocode(withLocation: point, parameters: params) { (results, error) in
guard let self = self else {
completion(.failure(UnknownError()))
return
}
if let error = error {
completion(.failure(error))
}
else if
let attributes = results?.first?.attributes,
let address = (attributes[.address] ?? attributes[.matchAddress]) as? String {
completion(.success(address))
else if let result = results?.first {
let key: String
if locator == self.onlineLocator {
key = OnlineGeocoderConfig.addressAttributeKey
}
else {
key = OfflineGeocoderConfig.addressAttributeKey
}
if let address = result.attributes?[key] as? String {
completion(.success(address))
}
else {
completion(.failure(MissingAttribute(key: key)))
}
}
else {
assertionFailure("Locator task unsupporting of required attribute key (\"\(String.address)\" for online locator, \"\(String.matchAddress)\" for offline locator).")
completion(.failure(NoResultsError()))
}
}
}
Expand All @@ -89,9 +132,3 @@ class AddressLocator {
removeCredentialsFromServices()
}
}

private extension String {
static let address = "Address"
static let matchAddress = "Match_addr"
static let offlineLocator = "AddressLocator"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ArcGIS

extension AppContext {

private var visibleAreaDefaultsKey: String { return "VisibleAreaDefaultsKey.\(String.webMapItemID)" }
private var visibleAreaDefaultsKey: String { return "VisibleAreaDefaultsKey.\(PortalConfig.webMapItemID)" }

/// The shared visible area `AGSViewpoint`.
///
Expand Down
183 changes: 0 additions & 183 deletions data-collection/data-collection/App Context/AppContext+WorkMode.swift

This file was deleted.

Loading