Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在创建Mapbox MGLShape之前验证geojson_Ios_Swift_Mapbox_Mapbox Ios - Fatal编程技术网

Ios 在创建Mapbox MGLShape之前验证geojson

Ios 在创建Mapbox MGLShape之前验证geojson,ios,swift,mapbox,mapbox-ios,Ios,Swift,Mapbox,Mapbox Ios,我正在使用iOS Mapbox SDK从来自第三方API的goejsonFeatureCollection数据创建一个MGLShapeCollectionFeature guard let feature = try? MGLShape(data: jsonData, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else { print("Could not cast to specifie

我正在使用iOS Mapbox SDK从来自第三方API的goejson
FeatureCollection
数据创建一个
MGLShapeCollectionFeature

guard let feature = try? MGLShape(data: jsonData, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else {
    print("Could not cast to specified MGLShapeCollectionFeature")
    return
}
问题是,API有时返回无效的geojson,其中单个
功能
不包含有效坐标(见下文),初始化
MGLShape
失败,原因是
“NSInvalidArgumentException”,原因是:“多点必须至少有一个顶点。”
,这是正确的

除了手动解析和修复geojson外,是否有其他方法可以过滤掉
功能集合中的无效
功能

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "icaoId": "KBOS",
        "airSigmetType": "AIRMET",
        "hazard": "IFR"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [

          ]
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "icaoId": "KSLC",
        "airSigmetType": "AIRMET",
        "hazard": "IFR"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -106.63,
              49.06
            ],
            [
              -104.12,
              48.95
            ],
            [
              -104.17,
              44.8
            ],
            [
              -106.91,
              46.38
            ],
            [
              -106.63,
              49.06
            ]
          ]
        ]
      }
    }
  ]
}

一种可能的解决方案是使用
Codable
将JSON解码为结构,过滤空项并将对象编码回:

struct FeatureCollection : Codable {
    let type : String
    var features : [Feature]
}

struct Feature : Codable {
    let type : String
    let properties : Properties
    let geometry : Geometry
}

struct Properties : Codable {
    let icaoId, airSigmetType, hazard : String
}

struct Geometry : Codable {
    let type : String
    let coordinates : [[[Double]]]
}

do {
    var result = try JSONDecoder().decode(FeatureCollection.self, from: jsonData)
    let filteredFeatures = result.features.filter{$0.geometry.coordinates != [[]]}
    result.features = filteredFeatures
    let filteredData = try JSONEncoder().encode(result)
    guard let feature = try? MGLShape(data: filteredData, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else {
        print("Could not cast to specified MGLShapeCollectionFeature")
        return
    }
} catch {
    print(error)
}

正如您所建议的,我自己进行了筛选,并在
数据上编写了此扩展

extension Data {

    func removeEmptyCoordinates() throws -> Data {
        guard var geojson = try JSONSerialization.jsonObject(with: self, options: []) as? [String: Any] else {
            return self
        }
        fix(geojson: &geojson,
            processFeatureIf: NSPredicate(format: "geometry.type == 'Polygon'"),
            keepFeatureIf: NSPredicate(format: "%K[0][SIZE] >= 2", "geometry.coordinates"))
        return try JSONSerialization.data(withJSONObject: geojson, options: [])
    }

    private func fix(geojson: inout [String: Any], processFeatureIf: NSPredicate, keepFeatureIf: NSPredicate) {
        guard let type = geojson["type"] as? String, type == "FeatureCollection" else {
            // "Not a FeatureCollection"
            return
        }
        // "No features to fix"
        guard let features = geojson["features"] as? [[String: Any]] else { return }

        let filtered = features.filter { feature in
            if !processFeatureIf.evaluate(with: feature) {
                // not processing
                return true
            }
            return keepFeatureIf.evaluate(with: feature)
        }
        geojson["features"] = filtered
    }
}

MGLShape
似乎没有这样做。你可能需要自己做。将JSON数据转换为Struct/Swift对象,执行过滤器以删除空坐标特性,然后将其重新转换为数据。这可能会起作用,但问题是形状有许多属性,我不想将它们解码为类型安全模型,但我希望它们可以通过Mapbox
MGLFeature
属性
访问。使用
Codable