diff --git a/apps/ios/GuideDogs.xcodeproj/project.pbxproj b/apps/ios/GuideDogs.xcodeproj/project.pbxproj index a0f47a49..9b0b5666 100644 --- a/apps/ios/GuideDogs.xcodeproj/project.pbxproj +++ b/apps/ios/GuideDogs.xcodeproj/project.pbxproj @@ -6420,7 +6420,7 @@ CODE_SIGN_ENTITLEMENTS = GuideDogs/Assets/PropertyLists/SoundscapeDF.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 23; + CURRENT_PROJECT_VERSION = 24; DEVELOPMENT_TEAM = ""; EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES; ENABLE_BITCODE = NO; @@ -6709,7 +6709,7 @@ CODE_SIGN_ENTITLEMENTS = GuideDogs/Assets/PropertyLists/Soundscape.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 23; + CURRENT_PROJECT_VERSION = 24; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = X4H33NKGKY; EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES; @@ -6769,7 +6769,7 @@ CODE_SIGN_ENTITLEMENTS = GuideDogs/Assets/PropertyLists/Soundscape.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 23; + CURRENT_PROJECT_VERSION = 24; DEVELOPMENT_TEAM = X4H33NKGKY; EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES; ENABLE_BITCODE = NO; diff --git a/apps/ios/GuideDogs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/ios/GuideDogs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/apps/ios/GuideDogs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/apps/ios/GuideDogs/Code/App/AppContext.swift b/apps/ios/GuideDogs/Code/App/AppContext.swift index c95dcd7c..febbb704 100644 --- a/apps/ios/GuideDogs/Code/App/AppContext.swift +++ b/apps/ios/GuideDogs/Code/App/AppContext.swift @@ -205,6 +205,59 @@ class AppContext { } // MARK: Actions + + /// Clears the map data cache + /// fixme: probably not the best place for this, but it is needed for updates + /// from version 1.1.2 + func clearMapDataCache() { + // copied from StatusViewController.swift + AppContext.shared.eventProcessor.hush(playSound: false) + guard let database = try? RealmHelper.getDatabaseRealm() else { + GDLogSpatialDataError("Error attempting to get database data!") + return + } + + var storedAddresses: [Address] = [] + for por in database.objects(ReferenceEntity.self) { + if let entity = por.getPOI() as? Address, storedAddresses.contains(where: { $0.key == entity.key }) == false { + // Copy the address + storedAddresses.append(Address(value: entity)) + } + } + + let success = AppContext.shared.spatialDataContext.clearCache() + + GDATelemetry.track("settings.clear_cache", with: ["keep_user_data": String(true)]) + + guard success else { + GDLogSpatialDataError("Error attempting to delete cached data!") + return + } + + guard storedAddresses.count > 0 else { + GDLogSpatialDataWarn("Cached data deleted") + return + } + + // Save stored addresses + guard let cache = try? RealmHelper.getCacheRealm() else { + GDLogSpatialDataError("Cached data deleted, but couldn't get cache realm to restore addresses!") + return + } + + do { + try cache.write { + for address in storedAddresses { + cache.create(Address.self, value: address, update: .modified) + } + } + } catch { + GDLogSpatialDataError("Cached data deleted, but couldn't restore addresses!") + return + } + + GDLogSpatialDataWarn("Cached data deleted and addresses restored") + } /// Starts the core components of the app including the sound context, the geolocation context, /// and the spatial data context. If the app is launched into the background by the system (e.g. @@ -240,6 +293,13 @@ class AppContext { cloudKeyValueStore.start() spatialDataContext.start() + // if the app was updated or there is no lastRunVersion, clear the cache + let lastRunVersion = UserDefaults.standard.string(forKey: "lastRunVersion") ?? "" + if lastRunVersion != AppContext.appVersion { + clearMapDataCache() + UserDefaults.standard.set(AppContext.appVersion, forKey: "lastRunVersion") + } + // Do not play the app launch sound if onboarding is in-progress if !(eventProcessor.activeBehavior is OnboardingBehavior) { eventProcessor.process(GlyphEvent(.appLaunch)) diff --git a/apps/ios/GuideDogs/Code/Visual UI/View Controllers/Settings/StatusTableViewController.swift b/apps/ios/GuideDogs/Code/Visual UI/View Controllers/Settings/StatusTableViewController.swift index 393449d2..47f1febb 100644 --- a/apps/ios/GuideDogs/Code/Visual UI/View Controllers/Settings/StatusTableViewController.swift +++ b/apps/ios/GuideDogs/Code/Visual UI/View Controllers/Settings/StatusTableViewController.swift @@ -191,14 +191,26 @@ extension StatusTableViewController { if SettingsContext.shared.automaticCalloutsEnabled { self.reenableCalloutsAfterReload = true SettingsContext.shared.automaticCalloutsEnabled = false - } + } + self.performSegue(withIdentifier: Segue.showLoadingModal, sender: self) - self.displayMarkersPrompt() + // Check that tiles can be downloaded before we attempt to delete the cache + AppContext.shared.spatialDataContext.checkServiceConnection { [weak self] (success) in + guard success else { + self?.displayUnableToClearCacheWarning() + return + } + + // Clear the cache and keep the markers + self?.clearCache(false) + } })) present(alert, animated: true, completion: nil) } + /// ask the user if they want to keep the markers. + /// This is not used, but could be reenabled for debug builds in the future. private func displayMarkersPrompt() { let alert = UIAlertController(title: GDLocalizedString("settings.clear_cache.markers.alert_title"), message: GDLocalizedString("settings.clear_cache.markers.alert_message"),