Skip to content

Commit 501251f

Browse files
authored
feat: catch objc exceptions, fix: int array literal (#393)
- Ios catch objc exceptions (parseExpression() exceptions coming from C++, so most won't get catched) - improve parseException()
1 parent 3b268f9 commit 501251f

File tree

3 files changed

+56
-36
lines changed

3 files changed

+56
-36
lines changed

maplibre_ios/ios/maplibre_ios.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Helper package for maplibre that provides iOS FFI bindings
1919
# Needs to be the same version as in maplibre_ios/Package.swift
2020
# FOR PREBUILT LIBRARY
2121
s.dependency 'MapLibre', '~> 6.19'
22+
s.dependency 'CwlCatchException', '~> 2.2'
2223

2324
# FOR LOCAL LIBRARY
2425
# s.vendored_frameworks = '.build/MapLibre.xcframework'

maplibre_ios/ios/maplibre_ios/Package.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ let package = Package(
1515
// Needs to be the same version as in ../maplibre_ios.podspec
1616
// FOR PREBUILT LIBRARY
1717
.package(url: "https://github.com/maplibre/maplibre-gl-native-distribution", .upToNextMinor(from: "6.19.0")),
18+
.package(url: "https://github.com/mattgallagher/CwlCatchException.git", .upToNextMinor(from: "2.2.0")),
1819
],
1920
targets: [
2021
.target(
@@ -25,6 +26,8 @@ let package = Package(
2526

2627
// FOR LOCAL LIBRARY
2728
// "MapLibre",
29+
30+
.product(name: "CwlCatchException", package: "CwlCatchException"),
2831
],
2932
cSettings: [
3033
.headerSearchPath("include/maplibre_ios"),
Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import CwlCatchException
12
import Foundation
23
import MapLibre
34
import UIKit
@@ -10,66 +11,81 @@ import UIKit
1011
@objc public static func addImageToStyle(
1112
target: NSObject, field: String, expression: NSExpression
1213
) {
13-
do {
14+
if let exception = NSException.catchException(in: {
1415
target.setValue(expression, forKey: field)
15-
} catch {
16-
print("Couldn't set expression in Helpers.addImageToStyle()")
16+
}) {
17+
print("⚠️ Couldn't set expression in Helpers.addImageToStyle(): \(exception)")
1718
}
1819
}
1920

2021
@objc public static func setExpression(
2122
target: NSObject, field: String, expression: NSExpression
2223
) {
23-
do {
24+
if let exception = NSException.catchException(in: {
2425
// https://developer.apple.com/documentation/objectivec/nsobject/1418139-setvalue
25-
try target.setValue(expression, forKey: field)
26-
} catch {
27-
print("Couldn't set expression in Helpers.setExpression()")
26+
target.setValue(expression, forKey: field)
27+
}) {
28+
print("⚠️ Couldn't set expression in Helpers.setExpression(): \(exception)")
2829
}
2930
}
3031

3132
@objc public static func parseExpression(
3233
propertyName: String, expression: String
3334
) -> NSExpression? {
34-
print("\(propertyName): \(expression)")
35-
do {
35+
print("Helpers.parseExpression(): \(propertyName): \(expression)")
36+
var result: NSExpression? = nil
37+
38+
if let exception = NSException.catchException(in: {
3639
// can't create an Expression using the default method if the data is a hex string
3740
if propertyName.contains("color"), expression.first == "#" {
38-
let color = UIColor(hexString: expression)
39-
return NSExpression(forConstantValue: color)
41+
guard let color = UIColor(hexString: expression) else {
42+
print("⚠️ Couldn't create UIColor from hex string: \(expression)")
43+
return
44+
}
45+
result = NSExpression(forConstantValue: color)
46+
return
4047
}
4148
if expression.starts(with: "[") {
4249
// can't create an Expression if the data of a literal is an array
43-
let json = try JSONSerialization.jsonObject(
44-
with: expression.data(using: .utf8)!,
45-
options: .fragmentsAllowed
46-
)
47-
// print("json: \(json)")
48-
if let offset = json as? [Any] {
49-
if offset.count == 2, offset.first is String,
50-
offset.first as? String == "literal"
51-
{
52-
if let vector = offset.last as? [Any] {
53-
if vector.count == 2 {
54-
if let x = vector.first as? Double,
55-
let y = vector.last as? Double
56-
{
57-
return NSExpression(
58-
forConstantValue: NSValue(
59-
cgVector: CGVector(dx: x, dy: y)))
60-
}
61-
}
50+
do {
51+
let json = try JSONSerialization.jsonObject(
52+
with: expression.data(using: .utf8)!,
53+
options: .fragmentsAllowed
54+
)
55+
56+
// print("json: \(json)")
57+
if let offset = json as? [Any] {
58+
// Case 1: ["literal", [x, y]]
59+
if let keyword = offset.first as? String,
60+
keyword == "literal",
61+
offset.count == 2,
62+
let vector = offset.last as? [Any],
63+
vector.count == 2,
64+
let x = vector.first as? Double,
65+
let y = vector.last as? Double
66+
{
67+
result = NSExpression(
68+
forConstantValue: NSValue(cgVector: CGVector(dx: x, dy: y))
69+
)
70+
return
6271
}
72+
73+
// Case 2: simple array literal like [x, y] or [5,5]
74+
result = NSExpression(forConstantValue: offset)
75+
return
6376
}
77+
result = NSExpression(mglJSONObject: json)
78+
return
79+
} catch {
80+
print("⚠️ JSON parsing error in Helpers.parseExpression(): \(error)")
81+
return
6482
}
65-
return NSExpression(mglJSONObject: json)
6683
}
6784
// parse as a constant value
68-
return NSExpression(forConstantValue: expression)
69-
70-
} catch {
71-
print("Couldn't parse Expression: " + expression)
85+
result = NSExpression(forConstantValue: expression)
86+
}) {
87+
print("⚠️ Couldn't parse expression in Helpers.parseExpression(): \(exception)")
7288
}
73-
return nil
89+
return result
7490
}
7591
}

0 commit comments

Comments
 (0)