diff --git a/apps/ios/GuideDogs.xcodeproj/project.pbxproj b/apps/ios/GuideDogs.xcodeproj/project.pbxproj index 5d3198cc..182f0ea8 100644 --- a/apps/ios/GuideDogs.xcodeproj/project.pbxproj +++ b/apps/ios/GuideDogs.xcodeproj/project.pbxproj @@ -669,6 +669,7 @@ 91745DD52AFB0E6C003EC104 /* GeoJsonGeometryTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91745DD42AFB0E6C003EC104 /* GeoJsonGeometryTest.swift */; }; 91745DD62AFB0F32003EC104 /* GeometryUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 914DEBDC2A3CE901007B161C /* GeometryUtilsTest.swift */; }; 91745DD82AFC48E0003EC104 /* GeoJsonFeatureTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91745DD72AFC48E0003EC104 /* GeoJsonFeatureTest.swift */; }; + 91745DDA2AFED7FF003EC104 /* GeoJsonFeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91745DD92AFED7FF003EC104 /* GeoJsonFeatureCollection.swift */; }; 91B6ADAA2AF19CB600FFE4E9 /* OSMServiceModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B6ADA92AF19CB600FFE4E9 /* OSMServiceModelTest.swift */; }; 91C82AAD2A5DCF040086D126 /* GeolocationManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91C82AAC2A5DCF040086D126 /* GeolocationManagerTest.swift */; }; 91C82ABE2A6B08500086D126 /* RouteGuidanceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91C82ABD2A6B08500086D126 /* RouteGuidanceTest.swift */; }; @@ -1589,6 +1590,7 @@ 915FF9F42ADE3F91002B3690 /* AuthoredActivityContentTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthoredActivityContentTest.swift; sourceTree = ""; }; 91745DD42AFB0E6C003EC104 /* GeoJsonGeometryTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonGeometryTest.swift; sourceTree = ""; }; 91745DD72AFC48E0003EC104 /* GeoJsonFeatureTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonFeatureTest.swift; sourceTree = ""; }; + 91745DD92AFED7FF003EC104 /* GeoJsonFeatureCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonFeatureCollection.swift; sourceTree = ""; }; 91B6ADA92AF19CB600FFE4E9 /* OSMServiceModelTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSMServiceModelTest.swift; sourceTree = ""; }; 91C82AAC2A5DCF040086D126 /* GeolocationManagerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = " GeolocationManagerTest.swift"; path = "UnitTests/Sensors/Geolocation/Geolocation Manager/ GeolocationManagerTest.swift"; sourceTree = SOURCE_ROOT; }; 91C82ABD2A6B08500086D126 /* RouteGuidanceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RouteGuidanceTest.swift; path = "UnitTests/Behaviors/Route Guidance/RouteGuidanceTest.swift"; sourceTree = SOURCE_ROOT; }; @@ -4516,6 +4518,7 @@ children = ( D298328F1E4BF80600352A5A /* GeoJsonFeature.swift */, D29832951E4E249700352A5A /* GeoJsonGeometry.swift */, + 91745DD92AFED7FF003EC104 /* GeoJsonFeatureCollection.swift */, ); name = OSM; sourceTree = ""; @@ -6104,6 +6107,7 @@ 31D0D7301E031A0E0087C847 /* UINavigationItem+Extension.swift in Sources */, 2821F61B220A6D1600D15EFF /* AuthoredActivityLoader.swift in Sources */, 6220D2D027CD7D4B0063BEA6 /* BeaconPickerItemView.swift in Sources */, + 91745DDA2AFED7FF003EC104 /* GeoJsonFeatureCollection.swift in Sources */, 287D3E8D22DE50340084B92B /* StatusTableViewController.swift in Sources */, 6258B3872469DAFA0051F60B /* UniversalLinkPathComponents.swift in Sources */, 28A16122283C3AF00081CFA4 /* TourGenerator.swift in Sources */, diff --git a/apps/ios/GuideDogs/Code/Data/Models/Cache Models/TileData.swift b/apps/ios/GuideDogs/Code/Data/Models/Cache Models/TileData.swift index 7b6aeaa2..bcb2839c 100644 --- a/apps/ios/GuideDogs/Code/Data/Models/Cache Models/TileData.swift +++ b/apps/ios/GuideDogs/Code/Data/Models/Cache Models/TileData.swift @@ -73,7 +73,7 @@ class TileData: Object { return VectorTile(quadKey: quadkey) } - convenience init(withParsedData json: OSMTileDataJson, quadkey: String, etag: String, superCategories: SuperCategories) { + convenience init(withParsedData json: GeoJsonFeatureCollection, quadkey: String, etag: String, superCategories: SuperCategories) { self.init() // Get the vector tile info diff --git a/apps/ios/GuideDogs/Code/Data/Services/Helpers/ServiceModel.swift b/apps/ios/GuideDogs/Code/Data/Services/Helpers/ServiceModel.swift index 3bec6152..14888b38 100644 --- a/apps/ios/GuideDogs/Code/Data/Services/Helpers/ServiceModel.swift +++ b/apps/ios/GuideDogs/Code/Data/Services/Helpers/ServiceModel.swift @@ -148,7 +148,7 @@ class ServiceModel { return json as? [String: Any] } - static func validateJsonResponse(request: URLRequest, response: URLResponse?, data: Data?, error: Error?, callback: @escaping (HTTPStatusCode, Error?) -> Void) -> (HTTPStatusCode, String, OSMTileDataJson)? { + static func validateJsonResponse(request: URLRequest, response: URLResponse?, data: Data?, error: Error?, callback: @escaping (HTTPStatusCode, Error?) -> Void) -> (HTTPStatusCode, String, GeoJsonFeatureCollection)? { // Some more housekeeping ServiceModel.logNetworkResponse(response, request: request, error: error) @@ -194,7 +194,7 @@ class ServiceModel { } // If we get this far, then the data property should not be nil, and it should be valid JSON - guard let data = data, let parsed = try? JSONDecoder().decode(OSMTileDataJson.self, from: data) else { + guard let data = data, let parsed = try? JSONDecoder().decode(GeoJsonFeatureCollection.self, from: data) else { DispatchQueue.main.async { callback(status, ServiceError.jsonParseFailed) } diff --git a/apps/ios/GuideDogs/Code/Data/Services/OSM/OSMServiceModel.swift b/apps/ios/GuideDogs/Code/Data/Services/OSM/OSMServiceModel.swift index 8dc32fb7..61d0090f 100644 --- a/apps/ios/GuideDogs/Code/Data/Services/OSM/OSMServiceModel.swift +++ b/apps/ios/GuideDogs/Code/Data/Services/OSM/OSMServiceModel.swift @@ -23,50 +23,6 @@ enum ServiceError: Error { case jsonParseFailed } -final class FailableDecode: Decodable { - var result: Result - - public init(from decoder: Decoder) throws { - result = Result(catching: { try T(from: decoder) }) - } -} - -/// Represents the parsed json response from the OSM tiles service -final class OSMTileDataJson: Decodable { - var features: [GeoJsonFeature] - - private enum CodingKeys: CodingKey { - /// Contains an array of ``GeoJsonFeature``s - case features - /// Should always be `"FeatureCollection"` - case type - } - - enum OSMTileDataParseError: Error { - /// The `type` property of an ``OSMTileDataJson`` should always be `"FeatureCollection"` - case incorrectTypeField - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let type = try container.decode(String.self, forKey: .type) - guard type == "FeatureCollection" else { - throw OSMTileDataParseError.incorrectTypeField - } - - /// Some parsed features may error, since our ``GeoJsonFeature`` implementation requires a name - /// As a result, we simply filter out the failing ones - let parsed_features = try container.decode([FailableDecode].self, forKey: .features) - features = parsed_features.compactMap({ - switch $0.result { - case .success(let feature): return feature - case .failure(_): return nil - } - }) - - } -} - class OSMServiceModel: OSMServiceModelProtocol { /// Path to the tile server private static let path = "/tiles" diff --git a/apps/ios/GuideDogs/GeoJsonFeatureCollection.swift b/apps/ios/GuideDogs/GeoJsonFeatureCollection.swift new file mode 100644 index 00000000..334a6b02 --- /dev/null +++ b/apps/ios/GuideDogs/GeoJsonFeatureCollection.swift @@ -0,0 +1,53 @@ +// +// GeoJsonFeatureCollection.swift +// Soundscape +// +// Created by Kai on 11/10/23. +// Copyright © 2023 Soundscape community. All rights reserved. +// + +import Foundation + +final class FailableDecode: Decodable { + var result: Result + + public init(from decoder: Decoder) throws { + result = Result(catching: { try T(from: decoder) }) + } +} + +/// Represents the parsed json response from the OSM tiles service +final class GeoJsonFeatureCollection: Decodable { + var features: [GeoJsonFeature] + + private enum CodingKeys: CodingKey { + /// Contains an array of ``GeoJsonFeature``s + case features + /// Should always be `"FeatureCollection"` + case type + } + + enum GeoJsonFeatureCollectionParseError: Error { + /// The `type` property of an ``GeoJsonFeatureCollection`` should always be `"FeatureCollection"` + case incorrectTypeField + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let type = try container.decode(String.self, forKey: .type) + guard type == "FeatureCollection" else { + throw GeoJsonFeatureCollectionParseError.incorrectTypeField + } + + /// Some parsed features may error, since our ``GeoJsonFeature`` implementation requires a name + /// As a result, we simply filter out the failing ones + let parsed_features = try container.decode([FailableDecode].self, forKey: .features) + features = parsed_features.compactMap({ + switch $0.result { + case .success(let feature): return feature + case .failure(_): return nil + } + }) + + } +}