iOS GPX 框架

这是一个用于解析/生成 GPX 文件的通用模块。该模块从 URL 或字符串解析 GPX,并创建 GPX 结构的 Swift 实例。

如何安装?

从 Xcode 安装

  1. 通过在 Xcode 的菜单栏中选择 FileAdd Packages… 来添加软件包。

  2. 使用仓库的 URL 搜索软件包

https://github.com/isklikas/iOS-GPX-Framework.git
  1. 接下来,将依赖规则设置为 Up to Next Minor Version(直到下一个小版本)。

  2. 然后,选择Add Package(添加软件包)。

或者,将 GPX 添加到 Package.swift 清单文件中

要通过 Package.swift 清单文件而不是 Xcode 集成,您可以将 GPX 添加到软件包的 dependencies 数组中

dependencies: [
  .package(
    name: "GPX",
    url: "https://github.com/isklikas/iOS-GPX-Framework.git",
    .upToNextMinor(from: "1.1.0")
  ),

  // Any other dependencies you have...
],

如何使用?

对于每个函数,必须导入 GPX 框架。

  1. 导入 GPX 模块

    import GPX;

解析 GPX 文件

  1. 要解析 GPX 文件,请调用 parse 方法。您可以通过调用 async 函数,使用 completion handler,或者通过遵循 GPXParsing 协议来完成。例如

    let urlPath = Bundle.main.url(forResource: "mystic_basin_trail", withExtension: "gpx");
    let parser = GPXParser(urlPath);
    
    // Delegate Approach
    // parser?.delegate = self;
    // parser?.parse();
        
    // Completion Handler / Async - Await Approach.
    // To see how to use GPXRoot, you can refer to the test file
    if #available(iOS 15, macOS 10.15, *) {
        Task {
            if let rootElement = try? await parser?.parse() {
                let root = GPXRoot(withXMLElement: parsedElement);
            }
        }
    }
    else {
        parser?.parse(completion: { parseResult in
            switch parseResult {
            case .failure(let error):
                print(error.localizedDescription);
            case .success(let parsedElement):
                let root = GPXRoot(withXMLElement: parsedElement);
            }
        })
    }
    
    //MARK: Delegate Methods
    
    func parser(_ parser: GPXParser, didCompleteParsing rootXMLElement: GPXXMLElement) {
        let root = GPXRoot(withXMLElement: rootXMLElement);
        // Use the parsed GPX file as you wish, for an example you can refer to 
        // the test file in the git repo.
    }
    
    func parser(_ parser: GPXParser, didFailParsingWithError error: Error) {
        print(error.localizedDescription);
    }

保存 GPX 文件

  1. 要生成 GPX 文件,请初始化一个 GPXLogger 对象。有 3 种选择

    a. 使用坐标数组初始化

    // For such an example, you may also refere to the GPXTests file
    let coordinates: [CLLocationCoordinate2D]; // Your Coordinates Array
    let logger = GPXLogger(coordinates);

    b. 使用位置数组初始化

    let locations: [CLLocation]; // Your Locations Array
    let logger = GPXLogger(locations);
    • 在坐标/位置的 GPXLogger 初始化器中,有一个 savingPreference 可选属性。 默认选项是 .tracks

      • 要将位置保存为路线,您可以在初始化器中指定,如下所示

        let locations: [CLLocation]; // Your Locations Array
        let logger = GPXLogger(locations, savingPreference: .route);
      • 要将导出的路线保存为航点数组,您可以在初始化器中指定,如下所示

        // GPX Waypoints are normally intended to be used as landmark points and not as a travelled path.
        let coordinates: [CLLocationCoordinate2D]; // Your Coordinates Array
        let logger = GPXLogger(locations, savingPreference: .waypoints);
      • 要将位置保存为轨迹,您无需指定 savingPreference 属性,因为这是默认值。

    • 在坐标/位置的 GPXLogger 初始化器中,还有一个 creator 可选属性。 默认选项是 "iOS-GPX-Framework",但您可以将其更改为应用程序的名称

      let locations: [CLLocation]; // Your Coordinates Array
      let logger = GPXLogger(locations, creator: "developer.my-app.com");
            
      // Or, if you wish to also specify the savingPreference property:
      // let logger = GPXLogger(locations, creator: "developer.my-app.com", savingPreference: .route);

    c. 使用已经存在的 GPXRoot 对象初始化,该对象可以是您从文件解析并编辑过的,或者您为了使用比坐标/位置数组更多的元数据而生成的。

    let gpxRoot: GPXRoot; // Your Root Object
    let logger = GPXLogger(gpxRoot);
  2. 要获取导出的 GPX 字符串,请调用 export 方法,该方法将 GPX 文件导出为字符串。 然后以通常的方式进行保存

    let exportedGPX = logger.export();
    
    // The Application's Document path, from here, you can also point to a sub-directory of Documents, as long as you have created the folder first
    let documentsFolderURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    // Append directory path components first here, if any (and already created, as mentioned).
    
    // Name the file as you wish
    let filename = documentsFolderURL.appendingPathComponent("gpx-filename.gpx")
    
    // Lastly, save the file
    do {
        try exportedGPX.write(to: filename, atomically: true, encoding: String.Encoding.utf8)
    } 
    catch {
        // failed to write file – bad permissions, bad filename, missing permissions, or more likely it can't be converted to the encoding
        print(error.localizedDescription);
    }