diff --git a/livemap-ios-sdk.xcodeproj/project.pbxproj b/livemap-ios-sdk.xcodeproj/project.pbxproj index 217d306..7bef97c 100644 --- a/livemap-ios-sdk.xcodeproj/project.pbxproj +++ b/livemap-ios-sdk.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 06F8C673253F2775003B51B3 /* CameraView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F8C672253F2775003B51B3 /* CameraView.swift */; }; 06F8C67C2540704A003B51B3 /* CustomARView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F8C67B2540704A003B51B3 /* CustomARView.swift */; }; 06F8C67E2540707C003B51B3 /* CustomARView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06F8C67D2540707C003B51B3 /* CustomARView.xib */; }; + 224D88D227BD3CB0007C82D4 /* StructExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224D88D127BD3CB0007C82D4 /* StructExtensions.swift */; }; + 2298E16E27BAC79E00DC3503 /* JSONStructs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2298E16D27BAC79E00DC3503 /* JSONStructs.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -50,6 +52,8 @@ 06F8C672253F2775003B51B3 /* CameraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = ""; }; 06F8C67B2540704A003B51B3 /* CustomARView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomARView.swift; sourceTree = ""; }; 06F8C67D2540707C003B51B3 /* CustomARView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CustomARView.xib; sourceTree = ""; }; + 224D88D127BD3CB0007C82D4 /* StructExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StructExtensions.swift; sourceTree = ""; }; + 2298E16D27BAC79E00DC3503 /* JSONStructs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONStructs.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -84,6 +88,7 @@ 06BDC4192400133F00527F0F /* livemap-ios-sdk */ = { isa = PBXGroup; children = ( + 224D88D027BD3C93007C82D4 /* model */, 06F8C671253F2753003B51B3 /* utils */, 06BDC41A2400133F00527F0F /* livemap_ios_sdk.h */, 06BDC41B2400133F00527F0F /* Info.plist */, @@ -101,6 +106,15 @@ path = utils; sourceTree = ""; }; + 224D88D027BD3C93007C82D4 /* model */ = { + isa = PBXGroup; + children = ( + 2298E16D27BAC79E00DC3503 /* JSONStructs.swift */, + 224D88D127BD3CB0007C82D4 /* StructExtensions.swift */, + ); + path = model; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -210,6 +224,8 @@ 06F6069A2404206200EF43C1 /* WemapSDKActionsDelegate.swift in Sources */, 06F8C67C2540704A003B51B3 /* CustomARView.swift in Sources */, 06BDC423240014FD00527F0F /* Livemap.swift in Sources */, + 224D88D227BD3CB0007C82D4 /* StructExtensions.swift in Sources */, + 2298E16E27BAC79E00DC3503 /* JSONStructs.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -421,6 +437,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.getwemap.livemap-ios-sdk"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 arm64 x86_64 armv7s arm64e i386"; diff --git a/livemap-ios-sdk.xcodeproj/xcshareddata/xcschemes/universal.xcscheme b/livemap-ios-sdk.xcodeproj/xcshareddata/xcschemes/universal.xcscheme new file mode 100644 index 0000000..81a227a --- /dev/null +++ b/livemap-ios-sdk.xcodeproj/xcshareddata/xcschemes/universal.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/livemap-ios-sdk/Livemap.swift b/livemap-ios-sdk/Livemap.swift index 82599ad..43d7738 100644 --- a/livemap-ios-sdk/Livemap.swift +++ b/livemap-ios-sdk/Livemap.swift @@ -25,7 +25,7 @@ import WebKit @objc optional func onBookEventClicked(_ wemapController: wemapsdk, event: WemapEvent) @objc optional func onGoToPinpointClicked(_ wemapController: wemapsdk, pinpoint: WemapPinpoint) - @objc optional func onLivemapMoved(_ wemapController: wemapsdk, jsonString: String) + @objc optional func onMapMoved(_ wemapController: wemapsdk, jsonString: String) @objc optional func onMapClick(_ wemapController: wemapsdk, jsonString: String) @objc optional func onMapLongClick(_ wemapController: wemapsdk, jsonString: String) } @@ -206,16 +206,23 @@ public class wemapsdk: UIView, WKUIDelegate { delegate?.onUrlChange?(self, previousUrl: previousUrl, nextUrl: nextUrl) } - func onLivemapMoved(jsonString: String) { - delegate?.onLivemapMoved?(self, jsonString: jsonString) + // Objective C cannot epose the swift struct and we do not want to make a new NSObject + func onMapMoved(parsedStruct: MapMoved) { + if let jsonString = MapMoved.toJsonString(parsedStruct: parsedStruct) { + delegate?.onMapMoved?(self, jsonString: jsonString) + } } - func onMapClick(jsonString: String) { - delegate?.onMapClick?(self, jsonString: jsonString) + func onMapClick(parsedStruct: Coordinates) { + if let jsonString = Coordinates.toJsonString(parsedStruct: parsedStruct) { + delegate?.onMapClick?(self, jsonString: jsonString) + } } - func onMapLongClick(jsonString: String) { - delegate?.onMapClick?(self, jsonString: jsonString) + func onMapLongClick(parsedStruct: Coordinates) { + if let jsonString = Coordinates.toJsonString(parsedStruct: parsedStruct) { + delegate?.onMapLongClick?(self, jsonString: jsonString) + } } } @@ -255,12 +262,14 @@ extension wemapsdk { } else { urlStr += "token=\(configuration.token)&emmid=\(configuration.emmid)&clicktofullscreen=false" - if (configuration.maxbounds != "") + if (configuration.maxbounds != nil) { - urlStr += "&maxbounds=\(configuration.maxbounds)" + if let box: String = wemapsdk_config.maxBoundsToUrl(maxbounds: configuration.maxbounds) { + // without encoding, URL() becomes nil during creation + urlStr += "&maxbounds=" + box.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)! + } } } - webView.load( URLRequest(url: URL(string: urlStr)!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData) ) @@ -273,7 +282,7 @@ extension wemapsdk { extension wemapsdk: WKScriptMessageHandler { public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - // debugPrint("\(#function) :::: message [\(message.name)] :::: with body: \n\(message.body)\n<<<") + //debugPrint("\(#function) :::: message [\(message.name)] :::: with body: \n\(message.body)\n<<<") guard let command = WebCommands(rawValue: message.name) else { return } switch command { @@ -346,16 +355,26 @@ extension wemapsdk: WKScriptMessageHandler { onUserLogout() case .onLivemapMoved: - let s = message.body as? String - onLivemapMoved(jsonString: s!) + // https://stackoverflow.com/questions/64992931/how-do-i-convert-a-wkscriptmessage-body-to-a-struct + if let bodyDict = message.body as? NSDictionary { + if let parsedStruct: MapMoved = MapMoved.map(dict: bodyDict) { + onMapMoved(parsedStruct: parsedStruct) + } + } case .onMapClick: - let s = message.body as? String - onMapClick(jsonString: s!) + if let bodyDict = message.body as? NSDictionary { + if let parsedStruct: Coordinates = Coordinates.map(dict: bodyDict) { + onMapClick(parsedStruct: parsedStruct) + } + } case .onMapLongClick: - let s = message.body as? String - onMapLongClick(jsonString: s!) + if let bodyDict = message.body as? NSDictionary { + if let parsedStruct: Coordinates = Coordinates.map(dict: bodyDict) { + onMapLongClick(parsedStruct: parsedStruct) + } + } default: debugPrint("WARNING: Not supported message: \(message.name)") @@ -452,15 +471,15 @@ extension wemapsdk { }; const onLivemapMovedCallback = (json) => { - window.webkit.messageHandlers.onLivemapMoved.postMessage({type: 'livemapMoved', data: json}); + window.webkit.messageHandlers.onLivemapMoved.postMessage(json); }; const onMapClickCallback = (json) => { - window.webkit.messageHandlers.onMapClick.postMessage({type: 'mapClick', data: json}); + window.webkit.messageHandlers.onMapClick.postMessage(json); }; const onMapLongClickCallback = (json) => { - window.webkit.messageHandlers.onMapLongClick.postMessage({type: 'mapLongClick', data: json}); + window.webkit.messageHandlers.onMapLongClick.postMessage(json); }; promise = window.livemap.addEventListener('eventOpen', onEventOpenCallback); @@ -654,7 +673,7 @@ public struct WemapLocation: Codable { } public struct wemapsdk_config { - public init(token: String?, mapId: Int? = nil, livemapRootUrl: String? = nil, maxbound: String? = nil) { + public init(token: String?, mapId: Int? = nil, livemapRootUrl: String? = nil, maxbounds: BoundingBox? = nil) { self.token = token ?? "" if let mapId = mapId { self.emmid = mapId @@ -663,16 +682,40 @@ public struct wemapsdk_config { self.ufe = true } self.livemapRootUrl = livemapRootUrl ?? wemapsdk_config.defaultLivemapRootUrl - self.maxbounds = livemapRootUrl ?? "" + self.maxbounds = maxbounds ?? nil + } + + //public static let defaultLivemapRootUrl = "https://livemap.getwemap.com" + public static let defaultLivemapRootUrl = "https://livemapstaging.maaap.it" + + public static func maxBoundsFromUrl(maxbounds: String) -> BoundingBox? { + if let parsedStruct: MaxBoundsSnippet = MaxBoundsSnippet.map(string: maxbounds) { + let result: BoundingBox = BoundingBox( + northEast: Coordinates(latitude: parsedStruct._northEast?.lat, longitude: parsedStruct._northEast?.lng, altitude: nil), + southWest: Coordinates(latitude: parsedStruct._southWest?.lat, longitude: parsedStruct._southWest?.lng, altitude: nil) + ) + return result + } + return nil } - public static let defaultLivemapRootUrl = "https://livemap.getwemap.com" + public static func maxBoundsToUrl(maxbounds: BoundingBox?) -> String? { + if (maxbounds == nil) { + return nil + } + let maxbounds2: BoundingBox = maxbounds! + let result: MaxBoundsSnippet = MaxBoundsSnippet( + _northEast: MaxBoundsSnippetCoords(lat: maxbounds2.northEast?.latitude, lng: maxbounds2.northEast?.longitude), + _southWest: MaxBoundsSnippetCoords(lat: maxbounds2.southWest?.latitude, lng: maxbounds2.southWest?.longitude) + ) + return MaxBoundsSnippet.toJsonString(parsedStruct: result) + } public let token: String public let emmid: Int public var ufe: Bool = false public let livemapRootUrl: String - public let maxbounds: String + public let maxbounds: BoundingBox? } enum WebCommands: String { diff --git a/livemap-ios-sdk/model/JSONStructs.swift b/livemap-ios-sdk/model/JSONStructs.swift new file mode 100644 index 0000000..44b097b --- /dev/null +++ b/livemap-ios-sdk/model/JSONStructs.swift @@ -0,0 +1,66 @@ + +public struct Coordinates: Codable { + let latitude: Double?; + let longitude: Double?; + let altitude: Double?; + + /// - Parameters: + /// - latitude: Double + /// - longitude: Double + /// - altitude: Double + public init(latitude: Double? = nil, + longitude: Double? = nil, + altitude: Double? = nil) { + self.latitude = latitude + self.longitude = longitude + self.altitude = altitude + } +} + +public struct BoundingBox: Codable { + let northEast: Coordinates?; + let southWest: Coordinates?; + + /// - Parameters: + /// - northEast: Coordinates + /// - southWest: Coordinates + public init(northEast: Coordinates? = nil, + southWest: Coordinates? = nil) { + self.northEast = northEast + self.southWest = southWest + } +} + +public struct MapMoved: Codable { + let zoom: Double?; + let bounds: BoundingBox?; + let latitude: Double?; + let longitude: Double?; + + /// - Parameters: + /// - zoom: Double + /// - bounds: BoundingBox + /// - latitude: Double + /// - longitude: Double + public init(zoom: Double? = nil, + bounds: BoundingBox? = nil, + latitude: Double? = nil, + longitude: Double? = nil) { + self.zoom = zoom + self.bounds = bounds + self.latitude = latitude + self.longitude = longitude + } +} + +// from snippet.config.json +public struct MaxBoundsSnippet: Codable { + let _northEast: MaxBoundsSnippetCoords?; + let _southWest: MaxBoundsSnippetCoords?; +} + +public struct MaxBoundsSnippetCoords: Codable { + let lat: Double?; + let lng: Double?; +} + diff --git a/livemap-ios-sdk/model/StructExtensions.swift b/livemap-ios-sdk/model/StructExtensions.swift new file mode 100644 index 0000000..20cc70a --- /dev/null +++ b/livemap-ios-sdk/model/StructExtensions.swift @@ -0,0 +1,38 @@ + +// https://stackoverflow.com/questions/53367491/decode-json-string-to-class-object-swift +extension Decodable { // Codable + Decodable = Codable + static func map(dict: NSDictionary) -> Self? { + do { + let decoder = JSONDecoder() + let bodyStruct = try JSONSerialization.data(withJSONObject: dict) + let parsedStruct = try decoder.decode(Self.self, from: bodyStruct) + return parsedStruct + } catch let error { + print(error) + return nil + } + } + + static func map(string: String) -> Self? { + do { + let decoder = JSONDecoder() + let parsedStruct = try decoder.decode(Self.self, from: Data(string.utf8)) + return parsedStruct + } catch let error { + print(error) + return nil + } + } +} + +extension Encodable { // Codable + Decodable = Codable + + static func toJsonString(parsedStruct: Self) -> String? { + do { + let jsonData = try JSONEncoder().encode(parsedStruct) + let jsonString = String(data: jsonData, encoding: .utf8)! + return jsonString + } catch { print(error) } + return nil + } +} diff --git a/releases/v1.7.0/livemap_ios_sdk.xcframework.zip b/releases/v1.7.0/livemap_ios_sdk.xcframework.zip deleted file mode 100644 index 6ad7ea1..0000000 Binary files a/releases/v1.7.0/livemap_ios_sdk.xcframework.zip and /dev/null differ