├── .swift-version ├── Tests ├── LinuxMain.swift └── PolylineTests │ ├── Info.plist │ ├── XCTestManifests.swift │ ├── FunctionalPolylineTests.swift │ └── PolylineTests.swift ├── Polyline.xcodeproj ├── xcuserdata │ ├── rmor.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ ├── Polyline.xcscheme │ │ │ └── PolylineTests.xcscheme │ └── raphael.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── raphael.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── Polyline.xccheckout ├── xcshareddata │ └── xcschemes │ │ ├── PolylineWatch.xcscheme │ │ ├── PolylineTV.xcscheme │ │ ├── PolylineMac.xcscheme │ │ └── Polyline.xcscheme └── project.pbxproj ├── .travis └── build.sh ├── .cocoadocs.yml ├── .gitignore ├── .travis.yml ├── Sources └── Polyline │ ├── Info.plist │ ├── Polyline.h │ ├── CoreLocation.swift │ └── Polyline.swift ├── Package.swift ├── LICENSE.txt ├── Polyline.podspec └── README.md /.swift-version: -------------------------------------------------------------------------------- 1 | 5.0 2 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import PolylineTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += PolylineTests.__allTests() 7 | 8 | XCTMain(tests) 9 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcuserdata/rmor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/project.xcworkspace/xcuserdata/raphael.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raphaelmor/Polyline/HEAD/Polyline.xcodeproj/project.xcworkspace/xcuserdata/raphael.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Polyline.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.travis/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | if [[ $TRAVIS_OS_NAME == 'osx' ]]; then 6 | xcodebuild $ACTION -project Polyline.xcodeproj -scheme "$SCHEME" -destination "$DESTINATION" ONLY_ACTIVE_ARCH=NO 7 | swift build 8 | swift test 9 | fi 10 | 11 | if [[ $TRAVIS_OS_NAME == 'linux' ]]; then 12 | eval "$(curl -sL https://swiftenv.fuller.li/install.sh)" 13 | swift build 14 | fi 15 | -------------------------------------------------------------------------------- /.cocoadocs.yml: -------------------------------------------------------------------------------- 1 | highlight-font: '"GT Walsheim", "gt_walsheim_regular", "Avant Garde Gothic ITCW01Dm", "Avant Garde", "Helvetica Neue", "Arial" ' 2 | body: '"Helvetica Neue", "Arial", san-serif' 3 | code: '"Monaco", "Menlo", "Consolas", "Courier New", monospace' 4 | 5 | highlight-color: "#008A88" 6 | highlight-dark-color: "#005E5D" 7 | darker-color: "#C6B7B2" 8 | darker-dark-color: "#A8A8A8" 9 | background-color: "#F2F2F2" 10 | alt-link-color: "#004241" 11 | warning-color: "#B80E3D" 12 | 13 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcuserdata/raphael.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SuppressBuildableAutocreation 6 | 7 | 207F63FD19B5DF7E005261FA 8 | 9 | primary 10 | 11 | 12 | 207F640819B5DF7E005261FA 13 | 14 | primary 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | .DS_Store 4 | build/ 5 | .build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | *.xcuserstate 21 | 22 | # CocoaPods 23 | # 24 | # We recommend against adding the Pods directory to your .gitignore. However 25 | # you should judge for yourself, the pros and cons are mentioned at: 26 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 27 | # 28 | # Pods/ 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | os: 3 | - linux 4 | - osx 5 | osx_image: xcode12.2 6 | env: SCHEME= 7 | before_script: 8 | - export LANG=en_US.UTF-8 9 | - export SWIFT_VERSION=5.0 10 | script: 11 | - ./.travis/build.sh 12 | jobs: 13 | include: 14 | - os: osx 15 | env: SCHEME=Polyline ACTION=test DESTINATION='platform=iOS Simulator,name=iPhone 11,OS=14.2' ONLY_ACTIVE_ARCH=NO 16 | - os: osx 17 | env: SCHEME=PolylineMac ACTION=test DESTINATION='platform=OS X' 18 | - os: osx 19 | env: SCHEME=PolylineTV ACTION=test DESTINATION='platform=tvOS Simulator,name=Apple TV,OS=14.2' 20 | - os: osx 21 | env: SCHEME=PolylineWatch ACTION=build DESTINATION='platform=watchOS Simulator,name=Apple Watch Series 6 - 44mm,OS=7.1' 22 | exclude: 23 | - os: osx 24 | env: SCHEME= 25 | -------------------------------------------------------------------------------- /Tests/PolylineTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 5.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 7 23 | 24 | 25 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcuserdata/rmor.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Polyline.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | PolylineTests.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 207F63FD19B5DF7E005261FA 21 | 22 | primary 23 | 24 | 25 | 207F640819B5DF7E005261FA 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Sources/Polyline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 5.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 7 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Polyline", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .library( 11 | name: "Polyline", 12 | targets: ["Polyline"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 21 | .target( 22 | name: "Polyline", 23 | dependencies: []), 24 | .testTarget( 25 | name: "PolylineTests", 26 | dependencies: ["Polyline"]), 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Raphaël Mor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Sources/Polyline/Polyline.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Raphaël Mor 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #import 24 | 25 | // ! Project version number for Polyline. 26 | FOUNDATION_EXPORT double PolylineVersionNumber; 27 | 28 | // ! Project version string for Polyline. 29 | FOUNDATION_EXPORT const unsigned char PolylineVersionString[]; 30 | 31 | // In this header, you should import all the public headers of your framework using statements like #import -------------------------------------------------------------------------------- /Polyline.xcodeproj/project.xcworkspace/xcshareddata/Polyline.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 9077EB1E-81E3-4244-A802-AC91B9350FEB 9 | IDESourceControlProjectName 10 | Polyline 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 49CDAB8249A689DD2FB684F10E837CD2D77E0BE3 14 | https://github.com/raphaelmor/Polyline 15 | 16 | IDESourceControlProjectPath 17 | Polyline.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 49CDAB8249A689DD2FB684F10E837CD2D77E0BE3 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/raphaelmor/Polyline 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 49CDAB8249A689DD2FB684F10E837CD2D77E0BE3 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 49CDAB8249A689DD2FB684F10E837CD2D77E0BE3 36 | IDESourceControlWCCName 37 | Polyline 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Sources/Polyline/CoreLocation.swift: -------------------------------------------------------------------------------- 1 | // Polyline.swift 2 | // 3 | // Copyright (c) 2015 Raphaël Mor 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | #if canImport(CoreLocation) 25 | import CoreLocation 26 | #endif 27 | 28 | #if canImport(CoreLocation) 29 | /** 30 | A geographic coordinate. 31 | 32 | This is a compatibility shim to keep the library’s public interface consistent between Apple and non-Apple platforms that lack Core Location. On Apple platforms, you can use `CLLocationCoordinate2D` anywhere you see this type. 33 | */ 34 | public typealias LocationCoordinate2D = CLLocationCoordinate2D 35 | #else 36 | /** 37 | A geographic coordinate. 38 | */ 39 | public struct LocationCoordinate2D { 40 | public let latitude: Double 41 | public let longitude: Double 42 | 43 | public init(latitude: Double, longitude: Double) { 44 | self.latitude = latitude 45 | self.longitude = longitude 46 | } 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcshareddata/xcschemes/PolylineWatch.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcuserdata/rmor.xcuserdatad/xcschemes/Polyline.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcshareddata/xcschemes/PolylineTV.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcshareddata/xcschemes/PolylineMac.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcshareddata/xcschemes/Polyline.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 64 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/xcuserdata/rmor.xcuserdatad/xcschemes/PolylineTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Polyline.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint Polyline.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "Polyline" 19 | s.version = "5.1.0" 20 | s.summary = "Polyline encoder / decoder in swift" 21 | 22 | s.description = <<-DESC 23 | A Google Polyline encoder / decoder in swift 24 | * Encodes Polyline from [CLLocation] or from [CLLocationCoordinate2D] 25 | * Decodes Polyline to [CLLocation] or to [CLLocationCoordinate2D] 26 | * Encodes/Decodes associated levels 27 | DESC 28 | 29 | s.homepage = "https://github.com/raphaelmor/Polyline" 30 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 31 | 32 | 33 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 34 | # 35 | # Licensing your code is important. See http://choosealicense.com for more info. 36 | # CocoaPods will detect a license file if there is a named LICENSE* 37 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 38 | # 39 | 40 | s.license = { :type => "MIT", :file => "LICENSE.txt" } 41 | 42 | 43 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 44 | # 45 | # Specify the authors of the library, with email addresses. Email addresses 46 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 47 | # accepts just a name if you'd rather not provide an email address. 48 | # 49 | # Specify a social_media_url where others can refer to, for example a twitter 50 | # profile URL. 51 | # 52 | 53 | s.author = { "Raphaël Mor" => "raphael.mor@gmail.com" } 54 | s.social_media_url = "http://twitter.com/raphaelmor" 55 | 56 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 57 | # 58 | # If this Pod runs only on iOS or OS X, then specify the platform and 59 | # the deployment target. You can optionally include the target after the platform. 60 | # 61 | 62 | s.ios.deployment_target = "12.0" 63 | s.osx.deployment_target = "10.14" 64 | s.watchos.deployment_target = "5.0" 65 | s.tvos.deployment_target = "12.0" 66 | 67 | 68 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 69 | # 70 | # Specify the location from where the source should be retrieved. 71 | # Supports git, hg, bzr, svn and HTTP. 72 | # 73 | 74 | s.source = { :git => "https://github.com/raphaelmor/Polyline.git", :tag => "v#{s.version.to_s}" } 75 | 76 | 77 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 78 | # 79 | # CocoaPods is smart about how it includes source code. For source files 80 | # giving a folder will include any swift, h, m, mm, c & cpp files. 81 | # For header files it will include any header in the folder. 82 | # Not including the public_header_files will make all headers public. 83 | # 84 | 85 | s.source_files = "Sources/Polyline" 86 | 87 | # s.public_header_files = "Classes/**/*.h" 88 | 89 | 90 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 91 | # 92 | # A list of resources included with the Pod. These are copied into the 93 | # target bundle with a build phase script. Anything else will be cleaned. 94 | # You can preserve files from being cleaned, please don't preserve 95 | # non-essential files like tests, examples and documentation. 96 | # 97 | 98 | # s.resource = "icon.png" 99 | # s.resources = "Resources/*.png" 100 | 101 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 102 | 103 | 104 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 105 | # 106 | # Link your library with frameworks, or libraries. Libraries do not include 107 | # the lib prefix of their name. 108 | # 109 | 110 | # s.framework = "SomeFramework" 111 | # s.frameworks = "SomeFramework", "AnotherFramework" 112 | 113 | # s.library = "iconv" 114 | # s.libraries = "iconv", "xml2" 115 | 116 | 117 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 118 | # 119 | # If your library depends on compiler flags you can set them in the xcconfig hash 120 | # where they will only apply to your library. If you depend on other Podspecs 121 | # you can include multiple dependencies to ensure it works. 122 | 123 | s.requires_arc = true 124 | s.swift_version = "5.0" 125 | 126 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 127 | # s.dependency "JSONKit", "~> 1.4" 128 | 129 | end 130 | -------------------------------------------------------------------------------- /Tests/PolylineTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | #if !canImport(ObjectiveC) 2 | import XCTest 3 | 4 | extension FunctionalPolylineTests { 5 | // DO NOT MODIFY: This is autogenerated, use: 6 | // `swift test --generate-linuxmain` 7 | // to regenerate. 8 | static let __allTests__FunctionalPolylineTests = [ 9 | ("testAnotherValidPolylineShouldReturnValidLocationArray", testAnotherValidPolylineShouldReturnValidLocationArray), 10 | ("testDecodingPolyline", testDecodingPolyline), 11 | ("testEmptyArrayShouldBeEmptyString", testEmptyArrayShouldBeEmptyString), 12 | ("testEmptyLevelsShouldBeEmptyLevelArray", testEmptyLevelsShouldBeEmptyLevelArray), 13 | ("testEmptylevelsShouldBeEmptyString", testEmptylevelsShouldBeEmptyString), 14 | ("testEmptyPolylineShouldBeEmptyLocationArray", testEmptyPolylineShouldBeEmptyLocationArray), 15 | ("testHighNegativeRoundedValuesShouldBeEncodedProperly", testHighNegativeRoundedValuesShouldBeEncodedProperly), 16 | ("testHighRoundedValuesShouldBeEncodedProperly", testHighRoundedValuesShouldBeEncodedProperly), 17 | ("testInvalidLevelsShouldReturnNilLevelArray", testInvalidLevelsShouldReturnNilLevelArray), 18 | ("testInvalidPolylineShouldReturnEmptyLocationArray", testInvalidPolylineShouldReturnEmptyLocationArray), 19 | ("testLocationsArrayShouldBeEncodedProperly", testLocationsArrayShouldBeEncodedProperly), 20 | ("testLowNegativeRoundedValuesShouldBeEncodedProperly", testLowNegativeRoundedValuesShouldBeEncodedProperly), 21 | ("testLowRoundedValuesShouldBeEncodedProperly", testLowRoundedValuesShouldBeEncodedProperly), 22 | ("testMidNegativeRoundedValuesShouldBeEncodedProperly", testMidNegativeRoundedValuesShouldBeEncodedProperly), 23 | ("testMidRoundedValuesShouldBeEncodedProperly", testMidRoundedValuesShouldBeEncodedProperly), 24 | ("testMinimalNegativeDifferenceShouldBeEncodedProperly", testMinimalNegativeDifferenceShouldBeEncodedProperly), 25 | ("testMinimalPositiveDifferenceShouldBeEncodedProperly", testMinimalPositiveDifferenceShouldBeEncodedProperly), 26 | ("testSmallDecrementLocationArrayShouldBeEncodedProperly", testSmallDecrementLocationArrayShouldBeEncodedProperly), 27 | ("testSmallIncrementLocationArrayShouldBeEncodedProperly", testSmallIncrementLocationArrayShouldBeEncodedProperly), 28 | ("testValidlevelsShouldBeEncodedProperly", testValidlevelsShouldBeEncodedProperly), 29 | ("testValidLevelsShouldReturnValidLevelArray", testValidLevelsShouldReturnValidLevelArray), 30 | ("testValidPolylineShouldReturnValidLocationArray", testValidPolylineShouldReturnValidLocationArray), 31 | ("testZeroShouldBeEncodedProperly", testZeroShouldBeEncodedProperly), 32 | ] 33 | } 34 | 35 | extension PolylineTests { 36 | // DO NOT MODIFY: This is autogenerated, use: 37 | // `swift test --generate-linuxmain` 38 | // to regenerate. 39 | static let __allTests__PolylineTests = [ 40 | ("testAnotherValidPolylineShouldReturnValidLocationArray", testAnotherValidPolylineShouldReturnValidLocationArray), 41 | ("testCoordinatesEncoding", testCoordinatesEncoding), 42 | ("testEmptyArrayShouldBeEmptyString", testEmptyArrayShouldBeEmptyString), 43 | ("testEmptyLevelsShouldBeEmptyLevelArray", testEmptyLevelsShouldBeEmptyLevelArray), 44 | ("testEmptylevelsShouldBeEmptyString", testEmptylevelsShouldBeEmptyString), 45 | ("testEmptyPolylineConvertionShouldBeEmptyMKPolyline", testEmptyPolylineConvertionShouldBeEmptyMKPolyline), 46 | ("testEmptyPolylineShouldBeEmptyLocationArray", testEmptyPolylineShouldBeEmptyLocationArray), 47 | ("testHighNegativeRoundedValuesShouldBeEncodedProperly", testHighNegativeRoundedValuesShouldBeEncodedProperly), 48 | ("testHighRoundedValuesShouldBeEncodedProperly", testHighRoundedValuesShouldBeEncodedProperly), 49 | ("testInvalidLevelsShouldReturnNilLevelArray", testInvalidLevelsShouldReturnNilLevelArray), 50 | ("testInvalidPolylineShouldReturnNil", testInvalidPolylineShouldReturnNil), 51 | ("testLevelDecoding", testLevelDecoding), 52 | ("testLevelEncoding", testLevelEncoding), 53 | ("testLimitValueIsProperlyEncoded", testLimitValueIsProperlyEncoded), 54 | ("testLocationsArrayShouldBeEncodedProperly", testLocationsArrayShouldBeEncodedProperly), 55 | ("testLocationsEncoding", testLocationsEncoding), 56 | ("testLowNegativeRoundedValuesShouldBeEncodedProperly", testLowNegativeRoundedValuesShouldBeEncodedProperly), 57 | ("testLowRoundedValuesShouldBeEncodedProperly", testLowRoundedValuesShouldBeEncodedProperly), 58 | ("testMidNegativeRoundedValuesShouldBeEncodedProperly", testMidNegativeRoundedValuesShouldBeEncodedProperly), 59 | ("testMidRoundedValuesShouldBeEncodedProperly", testMidRoundedValuesShouldBeEncodedProperly), 60 | ("testMinimalNegativeDifferenceShouldBeEncodedProperly", testMinimalNegativeDifferenceShouldBeEncodedProperly), 61 | ("testMinimalPositiveDifferenceShouldBeEncodedProperly", testMinimalPositiveDifferenceShouldBeEncodedProperly), 62 | ("testNillevelsShouldBeNil", testNillevelsShouldBeNil), 63 | ("testPerformances", testPerformances), 64 | ("testPolylineConvertionToMKPolyline", testPolylineConvertionToMKPolyline), 65 | ("testPolylineConvertionToMKPolylineWhenEncodingFailed", testPolylineConvertionToMKPolylineWhenEncodingFailed), 66 | ("testPolylineDecodingToCoordinate", testPolylineDecodingToCoordinate), 67 | ("testPolylineDecodingToLocations", testPolylineDecodingToLocations), 68 | ("testPrecision", testPrecision), 69 | ("testPrecisionIsUsedProperly", testPrecisionIsUsedProperly), 70 | ("testPrecisionShouldBeUsedProperlyInDecoding", testPrecisionShouldBeUsedProperlyInDecoding), 71 | ("testPrecisionShouldBeUsedProperlyInEncoding", testPrecisionShouldBeUsedProperlyInEncoding), 72 | ("testSmallDecrementLocationArrayShouldBeEncodedProperly", testSmallDecrementLocationArrayShouldBeEncodedProperly), 73 | ("testSmallIncrementLocationArrayShouldBeEncodedProperly", testSmallIncrementLocationArrayShouldBeEncodedProperly), 74 | ("testSmallNegativeDifferencesShouldBeEncodedProperly", testSmallNegativeDifferencesShouldBeEncodedProperly), 75 | ("testValidlevelsShouldBeEncodedProperly", testValidlevelsShouldBeEncodedProperly), 76 | ("testValidLevelsShouldReturnValidLevelArray", testValidLevelsShouldReturnValidLevelArray), 77 | ("testValidPolylineShouldReturnValidLocationArray", testValidPolylineShouldReturnValidLocationArray), 78 | ("testZeroShouldBeEncodedProperly", testZeroShouldBeEncodedProperly), 79 | ] 80 | } 81 | 82 | public func __allTests() -> [XCTestCaseEntry] { 83 | return [ 84 | testCase(FunctionalPolylineTests.__allTests__FunctionalPolylineTests), 85 | testCase(PolylineTests.__allTests__PolylineTests), 86 | ] 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | [![Build Status](https://travis-ci.org/raphaelmor/Polyline.svg?branch=master)](https://travis-ci.org/raphaelmor/Polyline) 6 | [![CocoaPods](https://img.shields.io/cocoapods/v/Polyline.svg)](http://cocoadocs.org/docsets/Polyline) 7 | ![Swift 5](https://img.shields.io/badge/Swift-5.0-green.svg) 8 | [![Licence](http://img.shields.io/badge/Licence-MIT-lightgrey.svg)](https://github.com/raphaelmor/Polyline/blob/master/LICENSE.txt) 9 | 10 | Polyline encoder / decoder in Swift 11 | 12 | 1. [Features](#features) 13 | 2. [Requirements](#requirements) 14 | 3. [Integration](#integration) 15 | 4. [Usage](#usage) 16 | 5. [Notes](#notes) 17 | 6. [Contributors](#contributors) 18 | 7. [License](#license) 19 | 20 | ## Features 21 | 22 | - Encode a `CLLocationCoordinate2D` array to a polyline 23 | - Decode a polyline to an array of `CLLocationCoordinate2D` 24 | - Encode a `CLLocation` array to a polyline 25 | - Decode a polyline to an array of `CLLocation` 26 | - Encode/Decode associated levels (optional) 27 | - 100% Unit Test Coverage 28 | - Complete Documentation 29 | - Continuous integration with [Travis CI](http://travis-ci.org) 30 | - CocoaPod available 31 | - Convert to `MKPolyline` 32 | 33 | ### Planned for future releases 34 | 35 | - Convert to `GMSPolyline` 36 | - Example project 37 | - Filter locations available at a specific level 38 | 39 | ### Planned when support is available : 40 | 41 | - Code Coverage with [Coveralls](https://coveralls.io) 42 | 43 | ## Requirements 44 | 45 | - Xcode 11+ 46 | - iOS 12.0+ / Mac OS X 10.14+ / tvOS 12.0+ / watchOS 5.0+ / Linux 47 | - Swift 5.0 48 | 49 | --- 50 | 51 | 52 | ## Integration 53 | To use this library in your project you can use CocoaPods, Carthage, Swift Package Manager, and/or integrate it manually : 54 | 55 | ### CocoaPods 56 | You can integrate Polyline in your `Podfile` like this: 57 | 58 | ``` 59 | pod 'Polyline', '~> 5.0' 60 | ``` 61 | 62 | ### Carthage 63 | You can integrate Polyline in your `Cartfile` like this: 64 | 65 | ``` 66 | github "raphaelmor/Polyline" ~> 5.0 67 | ``` 68 | 69 | ### Swift Package Manager 70 | To integrate Polyline into an application using [Swift Package Manager](https://swift.org/package-manager/) within Xcode: 71 | 72 | 1. Go to File ‣ Swift Packages ‣ Add Package Dependency. 73 | 2. Enter `https://github.com/raphaelmor/Polyline.git` as the package repository and click Next. 74 | 3. Set Rules to Version, Up to Next Major, and enter `5.0.2` as the minimum version requirement. Click Next. 75 | 76 | Or to integrate Polyline into another Swift package, add the following package to the `dependencies` in your Package.swift file: 77 | 78 | ```swift 79 | .package(url: "https://github.com/raphaelmor/Polyline.git", from: "5.0.2") 80 | ``` 81 | 82 | ### Manual 83 | 84 | To install Polyline manually, add Polyline.xcodeproj to an Xcode workspace, then link your application to Polyline.framework. 85 | 86 | It is technically possible to install Polyline by adding Polyline.swift and CoreLocation.swift directly to your project, but this approach is not recommended as it may omit important files in the future. 87 | 88 | ## Usage 89 | 90 | ### Polyline Encoding 91 | 92 | Using `[CLLocationCoordinate2D]` (recommended) : 93 | 94 | ```swift 95 | let coordinates = [CLLocationCoordinate2D(latitude: 40.2349727, longitude: -3.7707443), 96 | CLLocationCoordinate2D(latitude: 44.3377999, longitude: 1.2112933)] 97 | 98 | let polyline = Polyline(coordinates: coordinates) 99 | let encodedPolyline: String = polyline.encodedPolyline 100 | 101 | // Or for a functional approach : 102 | let encodedPolyline: String = encodeCoordinates(coordinates) 103 | ``` 104 | 105 | Using `[CLLocation]` : 106 | 107 | ```swift 108 | let locations = [CLLocation(latitude: 40.2349727, longitude: -3.7707443), 109 | CLLocation(latitude: 44.3377999, longitude: 1.2112933)] 110 | 111 | let polyline = Polyline(locations: locations) 112 | let encodedPolyline: String = polyline.encodedPolyline 113 | 114 | // Or for a functional approach : 115 | let encodedPolyline: String = encodeLocations(locations) 116 | ``` 117 | 118 | You can encode levels too : 119 | 120 | ```swift 121 | let levels: [UInt32] = [0,1,2,255] 122 | 123 | let polyline = Polyline(coordinates: coordinates, levels: levels) 124 | let encodedLevels: String? = polyline.encodedLevels 125 | 126 | // Or for a functional approach : 127 | let encodedLevels: String = encodedLevels(levels) 128 | ``` 129 | 130 | 131 | ### Polyline Decoding 132 | 133 | You can decode to `[CLLocationCoordinate2D]` (recommended) : 134 | 135 | ```swift 136 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]") 137 | let decodedCoordinates: [CLLocationCoordinate2D]? = polyline.coordinates 138 | 139 | // Or for a functional approach : 140 | let coordinates: [CLLocationCoordinate2D]? = decodePolyline("qkqtFbn_Vui`Xu`l]") 141 | ``` 142 | 143 | You can also decode to `[CLLocation]` : 144 | 145 | ```swift 146 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]") 147 | let decodedLocations: [CLLocation]? = polyline.locations 148 | 149 | // Or for a functional approach : 150 | let locations: [CLLocation]? = decodePolyline("qkqtFbn_Vui`Xu`l]") 151 | ``` 152 | 153 | You can decode levels too : 154 | 155 | ```swift 156 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]", encodedLevels: "BA") 157 | let decodedLevels: [UInt32]? = polyline.levels 158 | 159 | // Or for a functional approach : 160 | let levels: [UInt32]? = decodeLevels("BA") 161 | ``` 162 | 163 | ### Polyline Precision 164 | 165 | Default precision is 1e5 : 0.12345 (5 digit precision used by Google), but you can specify your own precision in all API methods (and functions). 166 | 167 | ```swift 168 | // OSRM uses a 6 digit precision 169 | let polyline = Polyline(encodedPolyline: "ak{hRak{hR", precision: 1e6) 170 | ``` 171 | 172 | 173 | 174 | ## Notes 175 | This library tries to have consistent results with polylines generated by the [Google Maps iOS SDK](https://developers.google.com/maps/documentation/ios/). 176 | The online tool for [encoding polylines](https://developers.google.com/maps/documentation/utilities/polylineutility) has some minor inconsistencies regarding rounding (for example, 0.000015 is rounded to 0.00002 for latitudes, but 0.00001 for longitudes). 177 | 178 | This codes tries to adhere to the [GitHub Swift Style Guide](https://github.com/github/swift-style-guide) 179 | 180 | ## Contributors 181 | 182 | - [Raphaël Mor](http://github.com/raphaelmor) ([@raphaelmor](https://twitter.com/raphaelmor)): Creator 183 | - [Tom Taylor](https://tomtaylor.co.uk): Maintainer 184 | - [Minh Nguyễn](https://github.com/1ec5): Maintainer 185 | 186 | ## License 187 | Polyline is released under an MIT license. See [LICENSE.txt](https://github.com/raphaelmor/Polyline/blob/master/LICENSE.txt) for more information. 188 | -------------------------------------------------------------------------------- /Tests/PolylineTests/FunctionalPolylineTests.swift: -------------------------------------------------------------------------------- 1 | // PolylineTests.swift 2 | // 3 | // Copyright (c) 2015 Raphaël Mor 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #if canImport(CoreLocation) 24 | import CoreLocation 25 | #endif 26 | import XCTest 27 | 28 | import Polyline 29 | 30 | private let COORD_EPSILON: Double = 0.00001 31 | 32 | class FunctionalPolylineTests : XCTestCase { 33 | 34 | // MARK:- Encoding Coordinates 35 | 36 | func testEmptyArrayShouldBeEmptyString() { 37 | XCTAssertEqual(encodeCoordinates([]), "") 38 | } 39 | 40 | func testZeroShouldBeEncodedProperly() { 41 | let coordinates = [CLLocationCoordinate2D(latitude: 0, longitude: 0)] 42 | XCTAssertEqual(encodeCoordinates(coordinates), "??") 43 | } 44 | 45 | func testMinimalPositiveDifferenceShouldBeEncodedProperly() { 46 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001)] 47 | XCTAssertEqual(encodeCoordinates(coordinates), "AA") 48 | } 49 | 50 | func testLowRoundedValuesShouldBeEncodedProperly() { 51 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000014, longitude: 0.000014)] 52 | XCTAssertEqual(encodeCoordinates(coordinates), "AA") 53 | } 54 | 55 | func testMidRoundedValuesShouldBeEncodedProperly() { 56 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000015, longitude: 0.000015)] 57 | XCTAssertEqual(encodeCoordinates(coordinates), "CC") 58 | } 59 | 60 | func testHighRoundedValuesShouldBeEncodedProperly() { 61 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000016, longitude: 0.000016)] 62 | XCTAssertEqual(encodeCoordinates(coordinates), "CC") 63 | } 64 | 65 | func testMinimalNegativeDifferenceShouldBeEncodedProperly() { 66 | let coordinates = [CLLocationCoordinate2D(latitude: -0.00001, longitude: -0.00001)] 67 | XCTAssertEqual(encodeCoordinates(coordinates), "@@") 68 | } 69 | 70 | func testLowNegativeRoundedValuesShouldBeEncodedProperly() { 71 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000014, longitude: -0.000014)] 72 | XCTAssertEqual(encodeCoordinates(coordinates), "@@") 73 | } 74 | 75 | func testMidNegativeRoundedValuesShouldBeEncodedProperly() { 76 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000015, longitude: -0.000015)] 77 | XCTAssertEqual(encodeCoordinates(coordinates), "BB") 78 | } 79 | 80 | func testHighNegativeRoundedValuesShouldBeEncodedProperly() { 81 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000016, longitude: -0.000016)] 82 | XCTAssertEqual(encodeCoordinates(coordinates), "BB") 83 | } 84 | 85 | func testSmallIncrementLocationArrayShouldBeEncodedProperly() { 86 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001), 87 | CLLocationCoordinate2D(latitude: 0.00002, longitude: 0.00002)] 88 | XCTAssertEqual(encodeCoordinates(coordinates), "AAAA") 89 | } 90 | 91 | func testSmallDecrementLocationArrayShouldBeEncodedProperly() { 92 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001), 93 | CLLocationCoordinate2D(latitude: 0.00000, longitude: 0.00000)] 94 | XCTAssertEqual(encodeCoordinates(coordinates), "AA@@") 95 | } 96 | 97 | // MARK: - Decoding Coordinates 98 | 99 | func testEmptyPolylineShouldBeEmptyLocationArray() { 100 | let coordinates: [CLLocationCoordinate2D] = decodePolyline("")! 101 | 102 | XCTAssertEqual(coordinates.count, 0) 103 | } 104 | 105 | func testInvalidPolylineShouldReturnEmptyLocationArray() { 106 | XCTAssertNil(decodePolyline("invalidPolylineString") as [CLLocationCoordinate2D]?) 107 | } 108 | 109 | func testValidPolylineShouldReturnValidLocationArray() { 110 | let coordinates: [CLLocationCoordinate2D] = decodePolyline("_p~iF~ps|U_ulLnnqC_mqNvxq`@")! 111 | 112 | XCTAssertEqual(coordinates.count, 3) 113 | XCTAssertEqual(coordinates[0].latitude, 38.5, accuracy: COORD_EPSILON) 114 | XCTAssertEqual(coordinates[0].longitude, -120.2, accuracy: COORD_EPSILON) 115 | XCTAssertEqual(coordinates[1].latitude, 40.7, accuracy: COORD_EPSILON) 116 | XCTAssertEqual(coordinates[1].longitude, -120.95, accuracy: COORD_EPSILON) 117 | XCTAssertEqual(coordinates[2].latitude, 43.252, accuracy: COORD_EPSILON) 118 | XCTAssertEqual(coordinates[2].longitude, -126.453, accuracy: COORD_EPSILON) 119 | } 120 | 121 | func testAnotherValidPolylineShouldReturnValidLocationArray() { 122 | let coordinates: [CLLocationCoordinate2D] = decodePolyline("_ojiHa`tLh{IdCw{Gwc_@")! 123 | 124 | XCTAssertEqual(coordinates.count, 3) 125 | XCTAssertEqual(coordinates[0].latitude, 48.8832, accuracy: COORD_EPSILON) 126 | XCTAssertEqual(coordinates[0].longitude, 2.23761, accuracy: COORD_EPSILON) 127 | XCTAssertEqual(coordinates[1].latitude, 48.82747, accuracy: COORD_EPSILON) 128 | XCTAssertEqual(coordinates[1].longitude, 2.23694, accuracy: COORD_EPSILON) 129 | XCTAssertEqual(coordinates[2].latitude, 48.87303, accuracy: COORD_EPSILON) 130 | XCTAssertEqual(coordinates[2].longitude, 2.40154, accuracy: COORD_EPSILON) 131 | } 132 | 133 | // MARK:- Encoding levels 134 | 135 | func testEmptylevelsShouldBeEmptyString() { 136 | XCTAssertEqual(encodeLevels([]), "") 137 | } 138 | 139 | func testValidlevelsShouldBeEncodedProperly() { 140 | XCTAssertEqual(encodeLevels([0,1,2,3]), "?@AB") 141 | } 142 | 143 | // MARK:- Decoding levels 144 | 145 | func testEmptyLevelsShouldBeEmptyLevelArray() { 146 | if let resultArray = decodeLevels("") { 147 | XCTAssertEqual(resultArray.count, 0) 148 | } else { 149 | XCTFail("Level array should not be nil for empty string") 150 | } 151 | } 152 | 153 | func testInvalidLevelsShouldReturnNilLevelArray() { 154 | if let _ = decodeLevels("invalidLevelString") { 155 | XCTFail("Level array should be nil for invalid string") 156 | } else { 157 | //Success 158 | } 159 | } 160 | 161 | func testValidLevelsShouldReturnValidLevelArray() { 162 | if let resultArray = decodeLevels("?@AB~F") { 163 | XCTAssertEqual(resultArray.count, 5) 164 | XCTAssertEqual(resultArray[0], UInt32(0)) 165 | XCTAssertEqual(resultArray[1], UInt32(1)) 166 | XCTAssertEqual(resultArray[2], UInt32(2)) 167 | XCTAssertEqual(resultArray[3], UInt32(3)) 168 | XCTAssertEqual(resultArray[4], UInt32(255)) 169 | 170 | } else { 171 | XCTFail("Valid Levels should be decoded properly") 172 | } 173 | } 174 | 175 | // MARK: - Encoding Locations 176 | func testLocationsArrayShouldBeEncodedProperly() { 177 | #if canImport(CoreLocation) 178 | let locations = [CLLocation(latitude: 0.00001, longitude: 0.00001), 179 | CLLocation(latitude: 0.00000, longitude: 0.00000)] 180 | 181 | XCTAssertEqual(encodeLocations(locations), "AA@@") 182 | #endif 183 | } 184 | 185 | func testDecodingPolyline() { 186 | let coordinates = decodePolyline("afvnFdrebO@o@", precision: 1e5) as [LocationCoordinate2D]? 187 | XCTAssertNotNil(coordinates) 188 | XCTAssertEqual(coordinates?.count, 2) 189 | XCTAssertEqual(coordinates?.first?.latitude ?? 0.0, 39.27665, accuracy: 1e-5) 190 | XCTAssertEqual(coordinates?.first?.longitude ?? 0.0, -84.411389, accuracy: 1e-5) 191 | XCTAssertEqual(coordinates?.last?.latitude ?? 0.0, 39.276635, accuracy: 1e-5) 192 | XCTAssertEqual(coordinates?.last?.longitude ?? 0.0, -84.411148, accuracy: 1e-5) 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /Sources/Polyline/Polyline.swift: -------------------------------------------------------------------------------- 1 | // Polyline.swift 2 | // 3 | // Copyright (c) 2015 Raphaël Mor 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import Foundation 24 | #if canImport(CoreLocation) 25 | import CoreLocation 26 | #endif 27 | #if canImport(MapKit) && !os(watchOS) 28 | import MapKit 29 | #endif 30 | 31 | // MARK: - Public Classes - 32 | 33 | /// This class can be used for : 34 | /// 35 | /// - Encoding an [CLLocation] or a [CLLocationCoordinate2D] to a polyline String 36 | /// - Decoding a polyline String to an [CLLocation] or a [CLLocationCoordinate2D] 37 | /// - Encoding / Decoding associated levels 38 | /// 39 | /// it is aims to produce the same results as google's iOS sdk not as the online 40 | /// tool which is fuzzy when it comes to rounding values 41 | /// 42 | /// it is based on google's algorithm that can be found here : 43 | /// 44 | /// :see: https://developers.google.com/maps/documentation/utilities/polylinealgorithm 45 | public struct Polyline { 46 | 47 | /// The array of coordinates (nil if polyline cannot be decoded) 48 | public let coordinates: [LocationCoordinate2D]? 49 | /// The encoded polyline 50 | public let encodedPolyline: String 51 | 52 | /// The array of levels (nil if cannot be decoded, or is not provided) 53 | public let levels: [UInt32]? 54 | /// The encoded levels (nil if cannot be encoded, or is not provided) 55 | public let encodedLevels: String? 56 | 57 | /// The array of location (computed from coordinates) 58 | #if canImport(CoreLocation) 59 | public var locations: [CLLocation]? { 60 | return self.coordinates.map(toLocations) 61 | } 62 | #endif 63 | 64 | #if canImport(MapKit) && !os(watchOS) 65 | /// Convert polyline to MKPolyline to use with MapKit (nil if polyline cannot be decoded) 66 | @available(tvOS 9.2, *) 67 | public var mkPolyline: MKPolyline? { 68 | guard let coordinates = self.coordinates else { return nil } 69 | let mkPolyline = MKPolyline(coordinates: coordinates, count: coordinates.count) 70 | return mkPolyline 71 | } 72 | #endif 73 | 74 | // MARK: - Public Methods - 75 | 76 | /// This designated initializer encodes a `[CLLocationCoordinate2D]` 77 | /// 78 | /// - parameter coordinates: The `Array` of `LocationCoordinate2D`s (that is, `CLLocationCoordinate2D`s) that you want to encode 79 | /// - parameter levels: The optional `Array` of levels that you want to encode (default: `nil`) 80 | /// - parameter precision: The precision used for encoding (default: `1e5`) 81 | public init(coordinates: [LocationCoordinate2D], levels: [UInt32]? = nil, precision: Double = 1e5) { 82 | 83 | self.coordinates = coordinates 84 | self.levels = levels 85 | 86 | encodedPolyline = encodeCoordinates(coordinates, precision: precision) 87 | 88 | encodedLevels = levels.map(encodeLevels) 89 | } 90 | 91 | /// This designated initializer decodes a polyline `String` 92 | /// 93 | /// - parameter encodedPolyline: The polyline that you want to decode 94 | /// - parameter encodedLevels: The levels that you want to decode (default: `nil`) 95 | /// - parameter precision: The precision used for decoding (default: `1e5`) 96 | public init(encodedPolyline: String, encodedLevels: String? = nil, precision: Double = 1e5) { 97 | 98 | self.encodedPolyline = encodedPolyline 99 | self.encodedLevels = encodedLevels 100 | 101 | coordinates = decodePolyline(encodedPolyline, precision: precision) 102 | 103 | levels = self.encodedLevels.flatMap(decodeLevels) 104 | } 105 | 106 | #if canImport(CoreLocation) 107 | /// This init encodes a `[CLLocation]` 108 | /// 109 | /// - parameter locations: The `Array` of `CLLocation` that you want to encode 110 | /// - parameter levels: The optional array of levels that you want to encode (default: `nil`) 111 | /// - parameter precision: The precision used for encoding (default: `1e5`) 112 | public init(locations: [CLLocation], levels: [UInt32]? = nil, precision: Double = 1e5) { 113 | 114 | let coordinates = toCoordinates(locations) 115 | self.init(coordinates: coordinates, levels: levels, precision:precision) 116 | } 117 | #endif 118 | } 119 | 120 | // MARK: - Public Functions - 121 | 122 | /// This function encodes an `[CLLocationCoordinate2D]` to a `String` 123 | /// 124 | /// - parameter coordinates: The `Array` of `LocationCoordinate2D`s (that is, `CLLocationCoordinate2D`s) that you want to encode 125 | /// - parameter precision: The precision used to encode coordinates (default: `1e5`) 126 | /// 127 | /// - returns: A `String` representing the encoded Polyline 128 | public func encodeCoordinates(_ coordinates: [LocationCoordinate2D], precision: Double = 1e5) -> String { 129 | 130 | var previousCoordinate = IntegerCoordinates(0, 0) 131 | var encodedPolyline = "" 132 | 133 | for coordinate in coordinates { 134 | let intLatitude = Int(round(coordinate.latitude * precision)) 135 | let intLongitude = Int(round(coordinate.longitude * precision)) 136 | 137 | let coordinatesDifference = (intLatitude - previousCoordinate.latitude, intLongitude - previousCoordinate.longitude) 138 | 139 | encodedPolyline += encodeCoordinate(coordinatesDifference) 140 | 141 | previousCoordinate = (intLatitude,intLongitude) 142 | } 143 | 144 | return encodedPolyline 145 | } 146 | 147 | #if canImport(CoreLocation) 148 | /// This function encodes an `[CLLocation]` to a `String` 149 | /// 150 | /// - parameter coordinates: The `Array` of `CLLocation` that you want to encode 151 | /// - parameter precision: The precision used to encode locations (default: `1e5`) 152 | /// 153 | /// - returns: A `String` representing the encoded Polyline 154 | public func encodeLocations(_ locations: [CLLocation], precision: Double = 1e5) -> String { 155 | 156 | return encodeCoordinates(toCoordinates(locations), precision: precision) 157 | } 158 | #endif 159 | 160 | /// This function encodes an `[UInt32]` to a `String` 161 | /// 162 | /// - parameter levels: The `Array` of `UInt32` levels that you want to encode 163 | /// 164 | /// - returns: A `String` representing the encoded Levels 165 | public func encodeLevels(_ levels: [UInt32]) -> String { 166 | return levels.reduce("") { 167 | $0 + encodeLevel($1) 168 | } 169 | } 170 | 171 | /// This function decodes a `String` to a `[CLLocationCoordinate2D]?` 172 | /// 173 | /// - parameter encodedPolyline: `String` representing the encoded Polyline 174 | /// - parameter precision: The precision used to decode coordinates (default: `1e5`) 175 | /// 176 | /// - returns: A `[CLLocationCoordinate2D]` representing the decoded polyline if valid, `nil` otherwise 177 | public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -> [LocationCoordinate2D]? { 178 | let data = encodedPolyline.data(using: .utf8)! 179 | return data.withUnsafeBytes { byteArray -> [LocationCoordinate2D]? in 180 | let length = data.count 181 | var position = 0 182 | 183 | var decodedCoordinates = [LocationCoordinate2D]() 184 | 185 | var lat = 0.0 186 | var lon = 0.0 187 | 188 | while position < length { 189 | do { 190 | let resultingLat = try decodeSingleCoordinate(byteArray: byteArray, length: length, position: &position, precision: precision) 191 | lat += resultingLat 192 | 193 | let resultingLon = try decodeSingleCoordinate(byteArray: byteArray, length: length, position: &position, precision: precision) 194 | lon += resultingLon 195 | } catch { 196 | return nil 197 | } 198 | 199 | decodedCoordinates.append(LocationCoordinate2D(latitude: lat, longitude: lon)) 200 | } 201 | 202 | return decodedCoordinates 203 | } 204 | } 205 | 206 | #if canImport(CoreLocation) 207 | /// This function decodes a String to a [CLLocation]? 208 | /// 209 | /// - parameter encodedPolyline: String representing the encoded Polyline 210 | /// - parameter precision: The precision used to decode locations (default: 1e5) 211 | /// 212 | /// - returns: A [CLLocation] representing the decoded polyline if valid, nil otherwise 213 | public func decodePolyline(_ encodedPolyline: String, precision: Double = 1e5) -> [CLLocation]? { 214 | 215 | return decodePolyline(encodedPolyline, precision: precision).map(toLocations) 216 | } 217 | #endif 218 | 219 | /// This function decodes a `String` to an `[UInt32]` 220 | /// 221 | /// - parameter encodedLevels: The `String` representing the levels to decode 222 | /// 223 | /// - returns: A `[UInt32]` representing the decoded Levels if the `String` is valid, `nil` otherwise 224 | public func decodeLevels(_ encodedLevels: String) -> [UInt32]? { 225 | var remainingLevels = encodedLevels.unicodeScalars 226 | var decodedLevels = [UInt32]() 227 | 228 | while remainingLevels.count > 0 { 229 | 230 | do { 231 | let chunk = try extractNextChunk(&remainingLevels) 232 | let level = decodeLevel(chunk) 233 | decodedLevels.append(level) 234 | } catch { 235 | return nil 236 | } 237 | } 238 | 239 | return decodedLevels 240 | } 241 | 242 | 243 | // MARK: - Private - 244 | 245 | // MARK: Encode Coordinate 246 | 247 | private func encodeCoordinate(_ locationCoordinate: IntegerCoordinates) -> String { 248 | 249 | let latitudeString = encodeSingleComponent(locationCoordinate.latitude) 250 | let longitudeString = encodeSingleComponent(locationCoordinate.longitude) 251 | 252 | return latitudeString + longitudeString 253 | } 254 | 255 | private func encodeSingleComponent(_ value: Int) -> String { 256 | 257 | var intValue = value 258 | 259 | if intValue < 0 { 260 | intValue = intValue << 1 261 | intValue = ~intValue 262 | } else { 263 | intValue = intValue << 1 264 | } 265 | 266 | return encodeFiveBitComponents(intValue) 267 | } 268 | 269 | // MARK: Encode Levels 270 | 271 | private func encodeLevel(_ level: UInt32) -> String { 272 | return encodeFiveBitComponents(Int(level)) 273 | } 274 | 275 | private func encodeFiveBitComponents(_ value: Int) -> String { 276 | var remainingComponents = value 277 | 278 | var fiveBitComponent = 0 279 | var returnString = String() 280 | 281 | repeat { 282 | fiveBitComponent = remainingComponents & 0x1F 283 | 284 | if remainingComponents >= 0x20 { 285 | fiveBitComponent |= 0x20 286 | } 287 | 288 | fiveBitComponent += 63 289 | 290 | let char = UnicodeScalar(fiveBitComponent)! 291 | returnString.append(String(char)) 292 | remainingComponents = remainingComponents >> 5 293 | } while (remainingComponents != 0) 294 | 295 | return returnString 296 | } 297 | 298 | // MARK: Decode Coordinate 299 | 300 | // We use a byte array (UnsafePointer) here for performance reasons. Check with swift 2 if we can 301 | // go back to using [Int8] 302 | private func decodeSingleCoordinate(byteArray: UnsafeRawBufferPointer, length: Int, position: inout Int, precision: Double = 1e5) throws -> Double { 303 | 304 | guard position < length else { throw PolylineError.singleCoordinateDecodingError } 305 | 306 | let bitMask = Int8(0x1F) 307 | 308 | var coordinate: Int32 = 0 309 | 310 | var currentChar: Int8 311 | var componentCounter: Int32 = 0 312 | var component: Int32 = 0 313 | 314 | repeat { 315 | currentChar = Int8(byteArray[position]) - 63 316 | component = Int32(currentChar & bitMask) 317 | coordinate |= (component << (5*componentCounter)) 318 | position += 1 319 | componentCounter += 1 320 | } while ((currentChar & 0x20) == 0x20) && (position < length) && (componentCounter < 6) 321 | 322 | if (componentCounter == 6) && ((currentChar & 0x20) == 0x20) { 323 | throw PolylineError.singleCoordinateDecodingError 324 | } 325 | 326 | if (coordinate & 0x01) == 0x01 { 327 | coordinate = ~(coordinate >> 1) 328 | } else { 329 | coordinate = coordinate >> 1 330 | } 331 | 332 | return Double(coordinate) / precision 333 | } 334 | 335 | // MARK: Decode Levels 336 | 337 | private func extractNextChunk(_ encodedString: inout String.UnicodeScalarView) throws -> String { 338 | var currentIndex = encodedString.startIndex 339 | 340 | while currentIndex != encodedString.endIndex { 341 | let currentCharacterValue = Int32(encodedString[currentIndex].value) 342 | if isSeparator(currentCharacterValue) { 343 | let extractedScalars = encodedString[encodedString.startIndex...currentIndex] 344 | encodedString = String.UnicodeScalarView(encodedString[encodedString.index(after: currentIndex).. UInt32 { 356 | let scalarArray = [] + encodedLevel.unicodeScalars 357 | 358 | return UInt32(agregateScalarArray(scalarArray)) 359 | } 360 | 361 | private func agregateScalarArray(_ scalars: [UnicodeScalar]) -> Int32 { 362 | let lastValue = Int32(scalars.last!.value) 363 | 364 | let fiveBitComponents: [Int32] = scalars.map { scalar in 365 | let value = Int32(scalar.value) 366 | if value != lastValue { 367 | return (value - 63) ^ 0x20 368 | } else { 369 | return value - 63 370 | } 371 | } 372 | 373 | return Array(fiveBitComponents.reversed()).reduce(0) { ($0 << 5 ) | $1 } 374 | } 375 | 376 | // MARK: Utilities 377 | 378 | enum PolylineError: Error { 379 | case singleCoordinateDecodingError 380 | case chunkExtractingError 381 | } 382 | 383 | #if canImport(CoreLocation) 384 | private func toCoordinates(_ locations: [CLLocation]) -> [CLLocationCoordinate2D] { 385 | return locations.map {location in location.coordinate} 386 | } 387 | 388 | private func toLocations(_ coordinates: [CLLocationCoordinate2D]) -> [CLLocation] { 389 | return coordinates.map { coordinate in 390 | CLLocation(latitude:coordinate.latitude, longitude:coordinate.longitude) 391 | } 392 | } 393 | #endif 394 | 395 | private func isSeparator(_ value: Int32) -> Bool { 396 | return (value - 63) & 0x20 != 0x20 397 | } 398 | 399 | private typealias IntegerCoordinates = (latitude: Int, longitude: Int) 400 | -------------------------------------------------------------------------------- /Tests/PolylineTests/PolylineTests.swift: -------------------------------------------------------------------------------- 1 | // PolylineTests.swift 2 | // 3 | // Copyright (c) 2015 Raphaël Mor 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #if canImport(CoreLocation) 24 | import CoreLocation 25 | #endif 26 | import XCTest 27 | 28 | import Polyline 29 | 30 | private let COORD_EPSILON_1e5: Double = 0.00001 31 | private let COORD_EPSILON_1e6: Double = 0.000001 32 | 33 | class PolylineTests:XCTestCase { 34 | 35 | // MARK:- Encoding Coordinates 36 | 37 | func testEmptyArrayShouldBeEmptyString() { 38 | let sut = Polyline(coordinates: []) 39 | XCTAssertEqual(sut.encodedPolyline, "") 40 | } 41 | 42 | func testZeroShouldBeEncodedProperly() { 43 | let coordinates = [CLLocationCoordinate2D(latitude: 0, longitude: 0)] 44 | 45 | let sut = Polyline(coordinates: coordinates) 46 | XCTAssertEqual(sut.encodedPolyline, "??") 47 | } 48 | 49 | func testMinimalPositiveDifferenceShouldBeEncodedProperly() { 50 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001)] 51 | 52 | let sut = Polyline(coordinates: coordinates) 53 | XCTAssertEqual(sut.encodedPolyline, "AA") 54 | } 55 | 56 | func testLowRoundedValuesShouldBeEncodedProperly() { 57 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000014, longitude: 0.000014)] 58 | 59 | let sut = Polyline(coordinates: coordinates) 60 | XCTAssertEqual(sut.encodedPolyline, "AA") 61 | } 62 | 63 | func testMidRoundedValuesShouldBeEncodedProperly() { 64 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000015, longitude: 0.000015)] 65 | 66 | let sut = Polyline(coordinates: coordinates) 67 | XCTAssertEqual(sut.encodedPolyline, "CC") 68 | } 69 | 70 | func testHighRoundedValuesShouldBeEncodedProperly() { 71 | let coordinates = [CLLocationCoordinate2D(latitude: 0.000016, longitude: 0.000016)] 72 | 73 | let sut = Polyline(coordinates: coordinates) 74 | XCTAssertEqual(sut.encodedPolyline, "CC") 75 | } 76 | 77 | func testMinimalNegativeDifferenceShouldBeEncodedProperly() { 78 | let coordinates = [CLLocationCoordinate2D(latitude: -0.00001, longitude: -0.00001)] 79 | 80 | let sut = Polyline(coordinates: coordinates) 81 | XCTAssertEqual(sut.encodedPolyline, "@@") 82 | } 83 | 84 | func testLowNegativeRoundedValuesShouldBeEncodedProperly() { 85 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000014, longitude: -0.000014)] 86 | 87 | let sut = Polyline(coordinates: coordinates) 88 | XCTAssertEqual(sut.encodedPolyline, "@@") 89 | } 90 | 91 | func testMidNegativeRoundedValuesShouldBeEncodedProperly() { 92 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000015, longitude: -0.000015)] 93 | 94 | let sut = Polyline(coordinates: coordinates) 95 | XCTAssertEqual(sut.encodedPolyline, "BB") 96 | } 97 | 98 | func testHighNegativeRoundedValuesShouldBeEncodedProperly() { 99 | let coordinates = [CLLocationCoordinate2D(latitude: -0.000016, longitude: -0.000016)] 100 | 101 | let sut = Polyline(coordinates: coordinates) 102 | XCTAssertEqual(sut.encodedPolyline, "BB") 103 | } 104 | 105 | func testSmallIncrementLocationArrayShouldBeEncodedProperly() { 106 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001), 107 | CLLocationCoordinate2D(latitude: 0.00002, longitude: 0.00002)] 108 | 109 | let sut = Polyline(coordinates: coordinates) 110 | XCTAssertEqual(sut.encodedPolyline, "AAAA") 111 | } 112 | 113 | func testSmallDecrementLocationArrayShouldBeEncodedProperly() { 114 | let coordinates = [CLLocationCoordinate2D(latitude: 0.00001, longitude: 0.00001), 115 | CLLocationCoordinate2D(latitude: 0.00000, longitude: 0.00000)] 116 | 117 | let sut = Polyline(coordinates: coordinates) 118 | XCTAssertEqual(sut.encodedPolyline, "AA@@") 119 | } 120 | 121 | func testPrecisionShouldBeUsedProperlyInEncoding() { 122 | let coordinates = [CLLocationCoordinate2D(latitude: 10.1234567, longitude:10.1234567)] 123 | 124 | var sut = Polyline(coordinates: coordinates) 125 | XCTAssertEqual(sut.encodedPolyline, "sfx|@sfx|@") 126 | 127 | sut = Polyline(coordinates: coordinates, precision: 1e5) 128 | XCTAssertEqual(sut.encodedPolyline, "sfx|@sfx|@") 129 | 130 | sut = Polyline(coordinates: coordinates, precision: 1e6) 131 | XCTAssertEqual(sut.encodedPolyline, "ak{hRak{hR") 132 | } 133 | 134 | // MARK:- Decoding Coordinates 135 | 136 | func testEmptyPolylineShouldBeEmptyLocationArray() { 137 | let sut = Polyline(encodedPolyline: "") 138 | XCTAssertTrue(sut.coordinates != nil) 139 | XCTAssertEqual((sut.coordinates!).count, 0) 140 | } 141 | 142 | func testInvalidPolylineShouldReturnNil() { 143 | let sut = Polyline(encodedPolyline: "invalidPolylineString") 144 | XCTAssertTrue(sut.coordinates == nil) 145 | } 146 | 147 | func testValidPolylineShouldReturnValidLocationArray() { 148 | let sut = Polyline(encodedPolyline: "_p~iF~ps|U_ulLnnqC_mqNvxq`@") 149 | 150 | let coordinates = sut.coordinates! 151 | 152 | XCTAssertEqual(coordinates.count, 3) 153 | XCTAssertEqual(coordinates[0].latitude, 38.5, accuracy: COORD_EPSILON_1e5) 154 | XCTAssertEqual(coordinates[0].longitude, -120.2, accuracy: COORD_EPSILON_1e5) 155 | XCTAssertEqual(coordinates[1].latitude, 40.7, accuracy: COORD_EPSILON_1e5) 156 | XCTAssertEqual(coordinates[1].longitude, -120.95, accuracy: COORD_EPSILON_1e5) 157 | XCTAssertEqual(coordinates[2].latitude, 43.252, accuracy: COORD_EPSILON_1e5) 158 | XCTAssertEqual(coordinates[2].longitude, -126.453, accuracy: COORD_EPSILON_1e5) 159 | } 160 | 161 | func testAnotherValidPolylineShouldReturnValidLocationArray() { 162 | let sut = Polyline(encodedPolyline: "_ojiHa`tLh{IdCw{Gwc_@") 163 | 164 | let coordinates = sut.coordinates! 165 | 166 | XCTAssertEqual(coordinates.count, 3) 167 | XCTAssertEqual(coordinates[0].latitude, 48.8832, accuracy: COORD_EPSILON_1e5) 168 | XCTAssertEqual(coordinates[0].longitude, 2.23761, accuracy: COORD_EPSILON_1e5) 169 | XCTAssertEqual(coordinates[1].latitude, 48.82747, accuracy: COORD_EPSILON_1e5) 170 | XCTAssertEqual(coordinates[1].longitude, 2.23694, accuracy: COORD_EPSILON_1e5) 171 | XCTAssertEqual(coordinates[2].latitude, 48.87303, accuracy: COORD_EPSILON_1e5) 172 | XCTAssertEqual(coordinates[2].longitude, 2.40154, accuracy: COORD_EPSILON_1e5) 173 | } 174 | 175 | func testPrecisionShouldBeUsedProperlyInDecoding() { 176 | 177 | var sut = Polyline(encodedPolyline: "sfx|@sfx|@") 178 | 179 | var coordinates = sut.coordinates! 180 | 181 | XCTAssertEqual(coordinates.count, 1) 182 | XCTAssertEqual(coordinates[0].latitude, 10.1234567, accuracy: COORD_EPSILON_1e5) 183 | 184 | sut = Polyline(encodedPolyline: "sfx|@sfx|@", precision: 1e5) 185 | 186 | coordinates = sut.coordinates! 187 | 188 | XCTAssertEqual(coordinates.count, 1) 189 | XCTAssertEqual(coordinates[0].latitude, 10.1234567, accuracy: COORD_EPSILON_1e5) 190 | 191 | sut = Polyline(encodedPolyline: "ak{hRak{hR", precision: 1e6) 192 | 193 | coordinates = sut.coordinates! 194 | 195 | XCTAssertEqual(coordinates.count, 1) 196 | XCTAssertEqual(coordinates[0].latitude, 10.1234567, accuracy: COORD_EPSILON_1e6) 197 | 198 | } 199 | 200 | // MARK:- Encoding levels 201 | 202 | func testEmptylevelsShouldBeEmptyString() { 203 | let sut = Polyline(coordinates: [], levels: []) 204 | 205 | XCTAssertTrue(sut.encodedLevels != nil) 206 | XCTAssertEqual(sut.encodedLevels!, "") 207 | } 208 | 209 | func testNillevelsShouldBeNil() { 210 | let sut = Polyline(coordinates: [], levels: nil) 211 | 212 | XCTAssertTrue(sut.encodedLevels == nil) 213 | } 214 | 215 | func testValidlevelsShouldBeEncodedProperly() { 216 | let sut = Polyline(coordinates: [], levels: [0,1,2,3]) 217 | 218 | XCTAssertEqual(sut.encodedLevels!, "?@AB") 219 | } 220 | 221 | // MARK:- Decoding levels 222 | 223 | func testEmptyLevelsShouldBeEmptyLevelArray() { 224 | let sut = Polyline(encodedPolyline: "", encodedLevels: "") 225 | 226 | XCTAssertTrue(sut.levels != nil,"Level array should not be nil for empty string") 227 | XCTAssertEqual((sut.levels!).count, 0) 228 | } 229 | 230 | func testInvalidLevelsShouldReturnNilLevelArray() { 231 | let sut = Polyline(encodedPolyline: "", encodedLevels: "invalidLevelString") 232 | 233 | XCTAssertTrue(sut.levels == nil, "Level array should be nil for invalid string") 234 | } 235 | 236 | func testValidLevelsShouldReturnValidLevelArray() { 237 | let sut = Polyline(encodedPolyline: "", encodedLevels: "?@AB~F") 238 | 239 | if let resultArray = sut.levels { 240 | XCTAssertEqual(resultArray.count, 5) 241 | XCTAssertEqual(resultArray[0], UInt32(0)) 242 | XCTAssertEqual(resultArray[1], UInt32(1)) 243 | XCTAssertEqual(resultArray[2], UInt32(2)) 244 | XCTAssertEqual(resultArray[3], UInt32(3)) 245 | XCTAssertEqual(resultArray[4], UInt32(255)) 246 | 247 | } else { 248 | XCTFail("Valid Levels should be decoded properly") 249 | } 250 | } 251 | 252 | // MARK:- Encoding Locations 253 | func testLocationsArrayShouldBeEncodedProperly() { 254 | #if canImport(CoreLocation) 255 | let locations = [CLLocation(latitude: 0.00001, longitude: 0.00001), 256 | CLLocation(latitude: 0.00000, longitude: 0.00000)] 257 | 258 | let sut = Polyline(locations: locations) 259 | XCTAssertEqual(sut.encodedPolyline, "AA@@") 260 | #endif 261 | } 262 | 263 | // MARK:- Issues non-regression tests 264 | 265 | // Github Issue 1 266 | func testSmallNegativeDifferencesShouldBeEncodedProperly() { 267 | let coordinates = [CLLocationCoordinate2D(latitude: 37.32721043, longitude: 122.02685069), 268 | CLLocationCoordinate2D(latitude: 37.32727259, longitude: 122.02685280), 269 | CLLocationCoordinate2D(latitude: 37.32733398, longitude: 122.02684998)] 270 | 271 | let sut = Polyline(coordinates: coordinates) 272 | XCTAssertEqual(sut.encodedPolyline, "anybFyjxgVK?K?") 273 | } 274 | 275 | // Github Issue 3 276 | func testLimitValueIsProperlyEncoded() { 277 | let sourceCoordinates = [CLLocationCoordinate2D(latitude: 0.00016, longitude: -0.00032)] 278 | 279 | let sut = Polyline(coordinates: sourceCoordinates) 280 | XCTAssertEqual(sut.encodedPolyline, "_@~@") 281 | } 282 | 283 | // Github issue 4 284 | func testPrecisionIsUsedProperly() { 285 | let encoded = "}gqefAridwgFrYEAhfA{@jDsAxBoBzBaDtB{iAX{c@EsU]uf@?_WR~@tPlTFfg@?jUNj|@eBtu@K?z]cAjLkDlJuFjGyG`IyCjIsAlM?|k@v@|dArQbv@k@jIpA?" 286 | let sut : [CLLocationCoordinate2D] = decodePolyline(encoded, precision: 1e6)! 287 | 288 | XCTAssertEqual(sut.count, 30) 289 | XCTAssertEqual(sut[0].latitude, 37.332111, accuracy: COORD_EPSILON_1e6) 290 | XCTAssertEqual(sut[0].longitude, -122.030762, accuracy: COORD_EPSILON_1e6) 291 | } 292 | 293 | // Github Issue 8 294 | func testPerformances() { 295 | self.measure { 296 | let _ = Polyline(encodedPolyline:"wamrIo{gnAnG_CVIm@{NEsDFgAHu@^{C`@sC@_As@eWEoBIw@?QDYd@oB@Uv@eDHOViAPwB@_ACUGQIcDYiIsA{a@EcB?iBD]JyBV}C@GJKDOCUMOO@MLy@@}ATI@McEQsLCcC?}@De@BQNe@gDcEgBsCSa@Yy@QiAS{D?gAJ_APmAt@wD`@eDDq@?aCk@uTcBif@KiBSkBa@wBUu@u@yB}CmHo@oAw@kA_@g@y@s@w@i@eJiF}BcB_BwAoCsDaB_DwLsWaBaDyB}Dm@qA_AcDEOIq@Sy@AuBBu@LgAR}@|@kCt@}Ab@s@^g@hAoAb@]jBkAdHqDt@[~@QxABNEHEdA}@TYbAyATQXKdC[n@Sr@c@r@}@|BwE~@eBjAyAvAaAlCaBlCoAjC_A|Cu@lLeBnDcAxBy@xDmBlEkCvDcCrFaEHGxAg@nAYf@Cz@@hCd@zAHj@MTIf@c@T]Zo@b@iBFo@DgA?k@CgAEa@Y_BoBeHo@sC{@iFg@qBk@aDqBeJaBcG}E_P{AsFq@kCk@eCwAmIm@yEk@cFg@eHU{FAiBMaIIiHImDSwF_@gGc@wFq@_G]aCc@yCcAsFiAeFCQ}FgUcEaRmBsJ_C}M_BaK{A{KsC_V_Gil@WqDy@kJk@eHyAeSu@mL]{Ha@kNI_GEkKFcV?mHKeHK}Cg@eKa@cFWmCm@}Ea@uCcCqMm@mCmAoEq@wBuA{DuAmD_BiDeDkG]u@{AwC{BaFiA_Dy@gCiA_Em@cCeAyEo@oDs@yEq@wFm@iHIyA]qIQiJIiBAkBDg@Ru@DOJSFc@Bc@AUIg@M[]aDIsAWyUs@cx@MqJ[wL_@gLg@uLo@oLiAkRo@_Iy@kH_@uCy@}Ey@mDaBcGkDsIgBkDgAaBiDiEkBqB}AkAmCaBaImDkAs@{BeBaBkBmBqCaCoEy@sBw@}Bq@aCoA{EeA_Fg@qCsAaJ_@sC]}CUqC_@qFIuAUkGQeIG}QCsRFuD?_CDgIAoJMyMUaLq@mO[wF}@uMe@oFc@kDu@wF{@{E_BwH[wAmDkL{HaToC}HwA{DiAkD_AuDyA_Ig@}Dg@wCyCiTi@cDy@qGcAeGkHyi@oAcJwBoPwAyJs@yFy@kFoFy_@wBeNkA}HcEuZeBqKOyAs@kEk@qEq@qE[cBWkBoAmHsBeOCQCuD\\{Bd@_Cz@aAbDuC~HuH|BsCjBqCdAgBrAgC~AwDjA{ClA}DrAmFf@_Cz@yE^aCh@_EVaCl@eHPcCp@qNbAuPf@_HtA}Nr@gG|@}GfAmHbB_JrAqG~AoItFkX`@_Cd@uDb@iEb@mFTiEXmJDyDAkDGeD]sIe@oG_A_Ko@gGaA{HwAyJi@eDqAoHiCiMmByH_EmOoCkIaGyR]_A}AcF_AiD}@_DwAiHc@oCa@kDa@gGQaEEwJFoD^}Ib@gF^kCZeCT}@x@oE\\yAtCaOb@iCv@qGV{CXwEJwE\\gh@RaMZsIv@iMX}CXyBnAeIj@qCx@cDrCkJrIeWdAmDp@mC`AsE\\gC~AeJTqBJq@VeDd@yH`@qMZaNx@c\\DaCDiAjAmc@f@iOjDwy@RqC|AcR|@}HtAiK~@oGn@oD|Hoa@vAwJ\\oCl@sGb@cF`@kHF_C`@iKJiH?gJIiDCoBo@yRsBga@[cREsFBeU`@sOTwGFeC~@cWf@wK~@_WbAu[vEmuAfAoXHiLHmTKe]GiCYoHY_Ew@aH}CmSwBkQgBcPw@uKScFCwCHeHZcIx@iOf@cMF}Bn@s^v@k\\n@i[j@aRNwGf@aPNsHb@kP|@yWp@wPLiFLqCbBej@?m@f@sQnAi_@b@mNlAg[VqE\\yELaCLuAdAmKXqB`@{D~BcTn@aGDm@NiATqC@i@F_BCeBOqDK}@e@yCAUDYBQFKn@Er@Bt@Jb@ApBS`CHfFIpEo@lFgB`FwC|@u@vCoCxA}AdEsG`CgFr@kBnAcE`BcHd@uCb@{Dj@kHNsCrAq`@T}ZFSFkAR_BBQDIrBwB|Ca@fGKhADbLfBlD`AhCz@pExBtBpAxCtBt@b@dBr@|@TjBTnBCbAK^IxCeAp@]xC}Bv@u@rCuDxSo\\jBsCfnAgnB|TiZjD}Df@a@bD{BpDsBfIyCvh@yXzB}@pAYnEi@tGArD}@nOsFxJuFjLeIvF}C`GkEtBmA|AUn@AdQP~Fo@zBNtO~B`CV`@@b@I~@o@d@i@|@gB`IeT|C{Ib@aB^iB~DmS`AsD~@eCb@_AXe@lBmCjd@m`@rJcIxKgKbEcDzQmS|CyCfDiCbDmBjBy@tEaBfIqAnQmBbA[|AY|EgBdF_CxH_GtAmAbDsDd@o@|e@mt@vCaEhHqIbL{KvF}DrNmJl@El@c@v@g@\\s@~@o@tG_E\\AbEiCZe@dB}@hGsA^EdCBfC[zNy@`Di@fAM`@Mz@_@~UcIdHcB~CWdACx]nAnFl@pBh@fEvBjRfKrP~IvGlCfB\\rF^n@@~AKpC]fYeH`@EfECrDZ`Ej@xFp@rBFtBErAKnCe@~Ae@lBu@~HcEjF{BpJkDzJaDpCmAtDiC|BqBhEaFbCeCXChBuApBcAb@EJ@RBPEFQh@a@pBq@R@RJL@H?Jd@Xf@TFNATONSDKz@o@XMp@OTMpBUfAQjDoA|BwAv@o@j@]~A_BtIyJtEcGpC_EHKLNNEDKBOC[tDqFtAaBt@u@jAeAfBuALKfA_BjDoEfDiC~@a@BCYyDYsBCQz@aAHIP~@") 297 | } 298 | } 299 | 300 | // MARK:- README code samples 301 | 302 | func testCoordinatesEncoding() { 303 | let coordinates = [CLLocationCoordinate2D(latitude: 40.2349727, longitude: -3.7707443), 304 | CLLocationCoordinate2D(latitude: 44.3377999, longitude: 1.2112933)] 305 | 306 | let polyline = Polyline(coordinates: coordinates) 307 | XCTAssertEqual(polyline.encodedPolyline, "qkqtFbn_Vui`Xu`l]") 308 | } 309 | 310 | func testLocationsEncoding() { 311 | #if canImport(CoreLocation) 312 | let locations = [CLLocation(latitude: 40.2349727, longitude: -3.7707443), 313 | CLLocation(latitude: 44.3377999, longitude: 1.2112933)] 314 | 315 | let polyline = Polyline(locations: locations) 316 | XCTAssertEqual(polyline.encodedPolyline, "qkqtFbn_Vui`Xu`l]") 317 | #endif 318 | } 319 | 320 | func testLevelEncoding() { 321 | let coordinates = [CLLocationCoordinate2D(latitude: 40.2349727, longitude: -3.7707443), 322 | CLLocationCoordinate2D(latitude: 44.3377999, longitude: 1.2112933)] 323 | 324 | let levels: [UInt32] = [0,1,2,255] 325 | 326 | let polyline = Polyline(coordinates: coordinates, levels: levels) 327 | let _ : String? = polyline.encodedLevels 328 | } 329 | 330 | func testPolylineDecodingToCoordinate() { 331 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]") 332 | 333 | let decodedCoordinates: [CLLocationCoordinate2D]? = polyline.coordinates 334 | XCTAssertEqual(2, decodedCoordinates!.count) 335 | } 336 | 337 | func testPolylineDecodingToLocations() { 338 | #if canImport(CoreLocation) 339 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]") 340 | let decodedLocations: [CLLocation]? = polyline.locations 341 | 342 | XCTAssertEqual(2, decodedLocations!.count) 343 | #endif 344 | } 345 | 346 | func testLevelDecoding() { 347 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]", encodedLevels: "BA") 348 | let decodedLevels: [UInt32]? = polyline.levels 349 | 350 | XCTAssertEqual(2, decodedLevels!.count) 351 | } 352 | 353 | func testPrecision() { 354 | // OSRM uses a 6 digit precision 355 | let _ = Polyline(encodedPolyline: "ak{hRak{hR", precision: 1e6) 356 | } 357 | 358 | #if canImport(MapKit) 359 | @available(tvOS 9.2, *) 360 | func testPolylineConvertionToMKPolyline() { 361 | let polyline = Polyline(encodedPolyline: "qkqtFbn_Vui`Xu`l]") 362 | 363 | let mkPolyline = polyline.mkPolyline 364 | XCTAssertNotNil(mkPolyline) 365 | XCTAssertTrue(polyline.coordinates?.count == mkPolyline?.pointCount) 366 | } 367 | #endif 368 | 369 | #if canImport(MapKit) 370 | @available(tvOS 9.2, *) 371 | func testPolylineConvertionToMKPolylineWhenEncodingFailed() { 372 | let polyline = Polyline(encodedPolyline: "invalidPolylineString") 373 | let mkPolyline = polyline.mkPolyline 374 | XCTAssertNil(mkPolyline) 375 | } 376 | #endif 377 | 378 | #if canImport(MapKit) 379 | @available(tvOS 9.2, *) 380 | func testEmptyPolylineConvertionShouldBeEmptyMKPolyline() { 381 | let polyline = Polyline(encodedPolyline: "") 382 | let mkPolyline = polyline.mkPolyline 383 | XCTAssertTrue(mkPolyline?.pointCount == 0) 384 | } 385 | #endif 386 | } 387 | -------------------------------------------------------------------------------- /Polyline.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 207F640419B5DF7E005261FA /* Polyline.h in Headers */ = {isa = PBXBuildFile; fileRef = 207F640319B5DF7E005261FA /* Polyline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 207F640E19B5DF7E005261FA /* PolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F640D19B5DF7E005261FA /* PolylineTests.swift */; }; 12 | 207F641B19B5E10C005261FA /* Polyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F641A19B5E10C005261FA /* Polyline.swift */; }; 13 | 28DD887E1AA1280C001CC005 /* FunctionalPolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DD887D1AA1280C001CC005 /* FunctionalPolylineTests.swift */; }; 14 | 64E1F8751A285A76002F25D3 /* Polyline.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 207F63FE19B5DF7E005261FA /* Polyline.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 15 | 91F783361CE4EB7F004E87E3 /* Polyline.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F7832C1CE4EB7E004E87E3 /* Polyline.framework */; }; 16 | DA01FB6F255361EF00335C7C /* CoreLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA01FB6E255361EF00335C7C /* CoreLocation.swift */; }; 17 | DA01FB70255361EF00335C7C /* CoreLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA01FB6E255361EF00335C7C /* CoreLocation.swift */; }; 18 | DA01FB71255361EF00335C7C /* CoreLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA01FB6E255361EF00335C7C /* CoreLocation.swift */; }; 19 | DA01FB72255361EF00335C7C /* CoreLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA01FB6E255361EF00335C7C /* CoreLocation.swift */; }; 20 | DA1A10661D003CF9009F82FA /* Polyline.h in Headers */ = {isa = PBXBuildFile; fileRef = 207F640319B5DF7E005261FA /* Polyline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | DA1A10691D003DFB009F82FA /* Polyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F641A19B5E10C005261FA /* Polyline.swift */; }; 22 | DA1A106A1D003E56009F82FA /* PolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F640D19B5DF7E005261FA /* PolylineTests.swift */; }; 23 | DA1A106B1D003E56009F82FA /* FunctionalPolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DD887D1AA1280C001CC005 /* FunctionalPolylineTests.swift */; }; 24 | DA1A107B1D003E88009F82FA /* Polyline.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA1A10711D003E88009F82FA /* Polyline.framework */; }; 25 | DA1A10881D003EA6009F82FA /* Polyline.h in Headers */ = {isa = PBXBuildFile; fileRef = 207F640319B5DF7E005261FA /* Polyline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | DA1A10891D003EA6009F82FA /* Polyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F641A19B5E10C005261FA /* Polyline.swift */; }; 27 | DA1A108A1D003EBB009F82FA /* PolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F640D19B5DF7E005261FA /* PolylineTests.swift */; }; 28 | DA1A108B1D003EBB009F82FA /* FunctionalPolylineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DD887D1AA1280C001CC005 /* FunctionalPolylineTests.swift */; }; 29 | DA1A10991D004035009F82FA /* Polyline.h in Headers */ = {isa = PBXBuildFile; fileRef = 207F640319B5DF7E005261FA /* Polyline.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | DA1A109A1D004035009F82FA /* Polyline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207F641A19B5E10C005261FA /* Polyline.swift */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 91F783371CE4EB7F004E87E3 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 207F63F519B5DF7E005261FA /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 91F7832B1CE4EB7E004E87E3; 39 | remoteInfo = PolylineMac; 40 | }; 41 | DA1A107C1D003E88009F82FA /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = 207F63F519B5DF7E005261FA /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = DA1A10701D003E88009F82FA; 46 | remoteInfo = PolylineTV; 47 | }; 48 | /* End PBXContainerItemProxy section */ 49 | 50 | /* Begin PBXCopyFilesBuildPhase section */ 51 | 64E1F8741A285A66002F25D3 /* Copy Frameworks */ = { 52 | isa = PBXCopyFilesBuildPhase; 53 | buildActionMask = 2147483647; 54 | dstPath = ""; 55 | dstSubfolderSpec = 10; 56 | files = ( 57 | 64E1F8751A285A76002F25D3 /* Polyline.framework in Copy Frameworks */, 58 | ); 59 | name = "Copy Frameworks"; 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXCopyFilesBuildPhase section */ 63 | 64 | /* Begin PBXFileReference section */ 65 | 207F63FE19B5DF7E005261FA /* Polyline.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Polyline.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | 207F640219B5DF7E005261FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 67 | 207F640319B5DF7E005261FA /* Polyline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Polyline.h; sourceTree = ""; }; 68 | 207F640919B5DF7E005261FA /* PolylineTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PolylineTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 207F640C19B5DF7E005261FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | 207F640D19B5DF7E005261FA /* PolylineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolylineTests.swift; sourceTree = ""; }; 71 | 207F641819B5E05A005261FA /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; 72 | 207F641A19B5E10C005261FA /* Polyline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Polyline.swift; sourceTree = ""; }; 73 | 207F641C19B5EDC3005261FA /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 74 | 28DD887D1AA1280C001CC005 /* FunctionalPolylineTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionalPolylineTests.swift; sourceTree = ""; }; 75 | 91F7832C1CE4EB7E004E87E3 /* Polyline.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Polyline.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 91F783351CE4EB7E004E87E3 /* PolylineTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PolylineTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 77 | DA01FB6E255361EF00335C7C /* CoreLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreLocation.swift; sourceTree = ""; }; 78 | DA1A10711D003E88009F82FA /* Polyline.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Polyline.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | DA1A107A1D003E88009F82FA /* PolylineTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PolylineTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | DA1A10911D00400D009F82FA /* Polyline.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Polyline.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 207F63FA19B5DF7E005261FA /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | 207F640619B5DF7E005261FA /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | 91F783281CE4EB7E004E87E3 /* Frameworks */ = { 99 | isa = PBXFrameworksBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | ); 103 | runOnlyForDeploymentPostprocessing = 0; 104 | }; 105 | 91F783321CE4EB7E004E87E3 /* Frameworks */ = { 106 | isa = PBXFrameworksBuildPhase; 107 | buildActionMask = 2147483647; 108 | files = ( 109 | 91F783361CE4EB7F004E87E3 /* Polyline.framework in Frameworks */, 110 | ); 111 | runOnlyForDeploymentPostprocessing = 0; 112 | }; 113 | DA1A106D1D003E88009F82FA /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | DA1A10771D003E88009F82FA /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | DA1A107B1D003E88009F82FA /* Polyline.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | DA1A108D1D00400D009F82FA /* Frameworks */ = { 129 | isa = PBXFrameworksBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | /* End PBXFrameworksBuildPhase section */ 136 | 137 | /* Begin PBXGroup section */ 138 | 207F63F419B5DF7E005261FA = { 139 | isa = PBXGroup; 140 | children = ( 141 | 35A28A5720E284B20030D1D9 /* Tests */, 142 | 35A28A5420E283D10030D1D9 /* Sources */, 143 | 207F641C19B5EDC3005261FA /* README.md */, 144 | 207F641819B5E05A005261FA /* LICENSE.txt */, 145 | 207F63FF19B5DF7E005261FA /* Products */, 146 | ); 147 | sourceTree = ""; 148 | }; 149 | 207F63FF19B5DF7E005261FA /* Products */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 207F63FE19B5DF7E005261FA /* Polyline.framework */, 153 | 207F640919B5DF7E005261FA /* PolylineTests.xctest */, 154 | 91F7832C1CE4EB7E004E87E3 /* Polyline.framework */, 155 | 91F783351CE4EB7E004E87E3 /* PolylineTests.xctest */, 156 | DA1A10711D003E88009F82FA /* Polyline.framework */, 157 | DA1A107A1D003E88009F82FA /* PolylineTests.xctest */, 158 | DA1A10911D00400D009F82FA /* Polyline.framework */, 159 | ); 160 | name = Products; 161 | sourceTree = ""; 162 | }; 163 | 207F640A19B5DF7E005261FA /* PolylineTests */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 207F640D19B5DF7E005261FA /* PolylineTests.swift */, 167 | 28DD887D1AA1280C001CC005 /* FunctionalPolylineTests.swift */, 168 | 207F640B19B5DF7E005261FA /* Supporting Files */, 169 | ); 170 | path = PolylineTests; 171 | sourceTree = ""; 172 | }; 173 | 207F640B19B5DF7E005261FA /* Supporting Files */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 207F640C19B5DF7E005261FA /* Info.plist */, 177 | ); 178 | name = "Supporting Files"; 179 | sourceTree = ""; 180 | }; 181 | 35A28A5420E283D10030D1D9 /* Sources */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 35A28A5520E283EA0030D1D9 /* Polyline */, 185 | ); 186 | path = Sources; 187 | sourceTree = ""; 188 | }; 189 | 35A28A5520E283EA0030D1D9 /* Polyline */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 207F640319B5DF7E005261FA /* Polyline.h */, 193 | 207F641A19B5E10C005261FA /* Polyline.swift */, 194 | DA01FB6E255361EF00335C7C /* CoreLocation.swift */, 195 | 35A28A5620E283F90030D1D9 /* Supporting Files */, 196 | ); 197 | path = Polyline; 198 | sourceTree = ""; 199 | }; 200 | 35A28A5620E283F90030D1D9 /* Supporting Files */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | 207F640219B5DF7E005261FA /* Info.plist */, 204 | ); 205 | name = "Supporting Files"; 206 | sourceTree = ""; 207 | }; 208 | 35A28A5720E284B20030D1D9 /* Tests */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | 207F640A19B5DF7E005261FA /* PolylineTests */, 212 | ); 213 | path = Tests; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXGroup section */ 217 | 218 | /* Begin PBXHeadersBuildPhase section */ 219 | 207F63FB19B5DF7E005261FA /* Headers */ = { 220 | isa = PBXHeadersBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 207F640419B5DF7E005261FA /* Polyline.h in Headers */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | 91F783291CE4EB7E004E87E3 /* Headers */ = { 228 | isa = PBXHeadersBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | DA1A10661D003CF9009F82FA /* Polyline.h in Headers */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | DA1A106E1D003E88009F82FA /* Headers */ = { 236 | isa = PBXHeadersBuildPhase; 237 | buildActionMask = 2147483647; 238 | files = ( 239 | DA1A10881D003EA6009F82FA /* Polyline.h in Headers */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | DA1A108E1D00400D009F82FA /* Headers */ = { 244 | isa = PBXHeadersBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | DA1A10991D004035009F82FA /* Polyline.h in Headers */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXHeadersBuildPhase section */ 252 | 253 | /* Begin PBXNativeTarget section */ 254 | 207F63FD19B5DF7E005261FA /* Polyline */ = { 255 | isa = PBXNativeTarget; 256 | buildConfigurationList = 207F641119B5DF7E005261FA /* Build configuration list for PBXNativeTarget "Polyline" */; 257 | buildPhases = ( 258 | 207F63F919B5DF7E005261FA /* Sources */, 259 | 207F63FA19B5DF7E005261FA /* Frameworks */, 260 | 207F63FB19B5DF7E005261FA /* Headers */, 261 | 207F63FC19B5DF7E005261FA /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | ); 267 | name = Polyline; 268 | productName = Polyline; 269 | productReference = 207F63FE19B5DF7E005261FA /* Polyline.framework */; 270 | productType = "com.apple.product-type.framework"; 271 | }; 272 | 207F640819B5DF7E005261FA /* PolylineTests */ = { 273 | isa = PBXNativeTarget; 274 | buildConfigurationList = 207F641419B5DF7E005261FA /* Build configuration list for PBXNativeTarget "PolylineTests" */; 275 | buildPhases = ( 276 | 207F640519B5DF7E005261FA /* Sources */, 277 | 207F640619B5DF7E005261FA /* Frameworks */, 278 | 207F640719B5DF7E005261FA /* Resources */, 279 | 64E1F8741A285A66002F25D3 /* Copy Frameworks */, 280 | ); 281 | buildRules = ( 282 | ); 283 | dependencies = ( 284 | ); 285 | name = PolylineTests; 286 | productName = PolylineTests; 287 | productReference = 207F640919B5DF7E005261FA /* PolylineTests.xctest */; 288 | productType = "com.apple.product-type.bundle.unit-test"; 289 | }; 290 | 91F7832B1CE4EB7E004E87E3 /* PolylineMac */ = { 291 | isa = PBXNativeTarget; 292 | buildConfigurationList = 91F7833D1CE4EB7F004E87E3 /* Build configuration list for PBXNativeTarget "PolylineMac" */; 293 | buildPhases = ( 294 | 91F783271CE4EB7E004E87E3 /* Sources */, 295 | 91F783281CE4EB7E004E87E3 /* Frameworks */, 296 | 91F783291CE4EB7E004E87E3 /* Headers */, 297 | 91F7832A1CE4EB7E004E87E3 /* Resources */, 298 | ); 299 | buildRules = ( 300 | ); 301 | dependencies = ( 302 | ); 303 | name = PolylineMac; 304 | productName = PolylineMac; 305 | productReference = 91F7832C1CE4EB7E004E87E3 /* Polyline.framework */; 306 | productType = "com.apple.product-type.framework"; 307 | }; 308 | 91F783341CE4EB7E004E87E3 /* PolylineMacTests */ = { 309 | isa = PBXNativeTarget; 310 | buildConfigurationList = 91F783401CE4EB7F004E87E3 /* Build configuration list for PBXNativeTarget "PolylineMacTests" */; 311 | buildPhases = ( 312 | 91F783311CE4EB7E004E87E3 /* Sources */, 313 | 91F783321CE4EB7E004E87E3 /* Frameworks */, 314 | 91F783331CE4EB7E004E87E3 /* Resources */, 315 | ); 316 | buildRules = ( 317 | ); 318 | dependencies = ( 319 | 91F783381CE4EB7F004E87E3 /* PBXTargetDependency */, 320 | ); 321 | name = PolylineMacTests; 322 | productName = PolylineMacTests; 323 | productReference = 91F783351CE4EB7E004E87E3 /* PolylineTests.xctest */; 324 | productType = "com.apple.product-type.bundle.unit-test"; 325 | }; 326 | DA1A10701D003E88009F82FA /* PolylineTV */ = { 327 | isa = PBXNativeTarget; 328 | buildConfigurationList = DA1A10861D003E88009F82FA /* Build configuration list for PBXNativeTarget "PolylineTV" */; 329 | buildPhases = ( 330 | DA1A106C1D003E88009F82FA /* Sources */, 331 | DA1A106D1D003E88009F82FA /* Frameworks */, 332 | DA1A106E1D003E88009F82FA /* Headers */, 333 | DA1A106F1D003E88009F82FA /* Resources */, 334 | ); 335 | buildRules = ( 336 | ); 337 | dependencies = ( 338 | ); 339 | name = PolylineTV; 340 | productName = PolylineTV; 341 | productReference = DA1A10711D003E88009F82FA /* Polyline.framework */; 342 | productType = "com.apple.product-type.framework"; 343 | }; 344 | DA1A10791D003E88009F82FA /* PolylineTVTests */ = { 345 | isa = PBXNativeTarget; 346 | buildConfigurationList = DA1A10871D003E88009F82FA /* Build configuration list for PBXNativeTarget "PolylineTVTests" */; 347 | buildPhases = ( 348 | DA1A10761D003E88009F82FA /* Sources */, 349 | DA1A10771D003E88009F82FA /* Frameworks */, 350 | DA1A10781D003E88009F82FA /* Resources */, 351 | ); 352 | buildRules = ( 353 | ); 354 | dependencies = ( 355 | DA1A107D1D003E88009F82FA /* PBXTargetDependency */, 356 | ); 357 | name = PolylineTVTests; 358 | productName = PolylineTVTests; 359 | productReference = DA1A107A1D003E88009F82FA /* PolylineTests.xctest */; 360 | productType = "com.apple.product-type.bundle.unit-test"; 361 | }; 362 | DA1A10901D00400D009F82FA /* PolylineWatch */ = { 363 | isa = PBXNativeTarget; 364 | buildConfigurationList = DA1A10961D00400D009F82FA /* Build configuration list for PBXNativeTarget "PolylineWatch" */; 365 | buildPhases = ( 366 | DA1A108C1D00400D009F82FA /* Sources */, 367 | DA1A108D1D00400D009F82FA /* Frameworks */, 368 | DA1A108E1D00400D009F82FA /* Headers */, 369 | DA1A108F1D00400D009F82FA /* Resources */, 370 | ); 371 | buildRules = ( 372 | ); 373 | dependencies = ( 374 | ); 375 | name = PolylineWatch; 376 | productName = PolylineWatch; 377 | productReference = DA1A10911D00400D009F82FA /* Polyline.framework */; 378 | productType = "com.apple.product-type.framework"; 379 | }; 380 | /* End PBXNativeTarget section */ 381 | 382 | /* Begin PBXProject section */ 383 | 207F63F519B5DF7E005261FA /* Project object */ = { 384 | isa = PBXProject; 385 | attributes = { 386 | LastSwiftMigration = 0700; 387 | LastSwiftUpdateCheck = 0730; 388 | LastUpgradeCheck = 1400; 389 | ORGANIZATIONNAME = "Raphael MOR"; 390 | TargetAttributes = { 391 | 207F63FD19B5DF7E005261FA = { 392 | CreatedOnToolsVersion = 6.0; 393 | LastSwiftMigration = 0900; 394 | }; 395 | 207F640819B5DF7E005261FA = { 396 | CreatedOnToolsVersion = 6.0; 397 | LastSwiftMigration = 0900; 398 | }; 399 | 91F7832B1CE4EB7E004E87E3 = { 400 | CreatedOnToolsVersion = 7.3.1; 401 | LastSwiftMigration = 1130; 402 | }; 403 | 91F783341CE4EB7E004E87E3 = { 404 | CreatedOnToolsVersion = 7.3.1; 405 | LastSwiftMigration = 1130; 406 | }; 407 | DA1A10701D003E88009F82FA = { 408 | CreatedOnToolsVersion = 7.3.1; 409 | }; 410 | DA1A10791D003E88009F82FA = { 411 | CreatedOnToolsVersion = 7.3.1; 412 | }; 413 | DA1A10901D00400D009F82FA = { 414 | CreatedOnToolsVersion = 7.3.1; 415 | LastSwiftMigration = 0800; 416 | }; 417 | }; 418 | }; 419 | buildConfigurationList = 207F63F819B5DF7E005261FA /* Build configuration list for PBXProject "Polyline" */; 420 | compatibilityVersion = "Xcode 3.2"; 421 | developmentRegion = en; 422 | hasScannedForEncodings = 0; 423 | knownRegions = ( 424 | en, 425 | Base, 426 | ); 427 | mainGroup = 207F63F419B5DF7E005261FA; 428 | productRefGroup = 207F63FF19B5DF7E005261FA /* Products */; 429 | projectDirPath = ""; 430 | projectRoot = ""; 431 | targets = ( 432 | 207F63FD19B5DF7E005261FA /* Polyline */, 433 | 207F640819B5DF7E005261FA /* PolylineTests */, 434 | 91F7832B1CE4EB7E004E87E3 /* PolylineMac */, 435 | 91F783341CE4EB7E004E87E3 /* PolylineMacTests */, 436 | DA1A10701D003E88009F82FA /* PolylineTV */, 437 | DA1A10791D003E88009F82FA /* PolylineTVTests */, 438 | DA1A10901D00400D009F82FA /* PolylineWatch */, 439 | ); 440 | }; 441 | /* End PBXProject section */ 442 | 443 | /* Begin PBXResourcesBuildPhase section */ 444 | 207F63FC19B5DF7E005261FA /* Resources */ = { 445 | isa = PBXResourcesBuildPhase; 446 | buildActionMask = 2147483647; 447 | files = ( 448 | ); 449 | runOnlyForDeploymentPostprocessing = 0; 450 | }; 451 | 207F640719B5DF7E005261FA /* Resources */ = { 452 | isa = PBXResourcesBuildPhase; 453 | buildActionMask = 2147483647; 454 | files = ( 455 | ); 456 | runOnlyForDeploymentPostprocessing = 0; 457 | }; 458 | 91F7832A1CE4EB7E004E87E3 /* Resources */ = { 459 | isa = PBXResourcesBuildPhase; 460 | buildActionMask = 2147483647; 461 | files = ( 462 | ); 463 | runOnlyForDeploymentPostprocessing = 0; 464 | }; 465 | 91F783331CE4EB7E004E87E3 /* Resources */ = { 466 | isa = PBXResourcesBuildPhase; 467 | buildActionMask = 2147483647; 468 | files = ( 469 | ); 470 | runOnlyForDeploymentPostprocessing = 0; 471 | }; 472 | DA1A106F1D003E88009F82FA /* Resources */ = { 473 | isa = PBXResourcesBuildPhase; 474 | buildActionMask = 2147483647; 475 | files = ( 476 | ); 477 | runOnlyForDeploymentPostprocessing = 0; 478 | }; 479 | DA1A10781D003E88009F82FA /* Resources */ = { 480 | isa = PBXResourcesBuildPhase; 481 | buildActionMask = 2147483647; 482 | files = ( 483 | ); 484 | runOnlyForDeploymentPostprocessing = 0; 485 | }; 486 | DA1A108F1D00400D009F82FA /* Resources */ = { 487 | isa = PBXResourcesBuildPhase; 488 | buildActionMask = 2147483647; 489 | files = ( 490 | ); 491 | runOnlyForDeploymentPostprocessing = 0; 492 | }; 493 | /* End PBXResourcesBuildPhase section */ 494 | 495 | /* Begin PBXSourcesBuildPhase section */ 496 | 207F63F919B5DF7E005261FA /* Sources */ = { 497 | isa = PBXSourcesBuildPhase; 498 | buildActionMask = 2147483647; 499 | files = ( 500 | 207F641B19B5E10C005261FA /* Polyline.swift in Sources */, 501 | DA01FB6F255361EF00335C7C /* CoreLocation.swift in Sources */, 502 | ); 503 | runOnlyForDeploymentPostprocessing = 0; 504 | }; 505 | 207F640519B5DF7E005261FA /* Sources */ = { 506 | isa = PBXSourcesBuildPhase; 507 | buildActionMask = 2147483647; 508 | files = ( 509 | 28DD887E1AA1280C001CC005 /* FunctionalPolylineTests.swift in Sources */, 510 | 207F640E19B5DF7E005261FA /* PolylineTests.swift in Sources */, 511 | ); 512 | runOnlyForDeploymentPostprocessing = 0; 513 | }; 514 | 91F783271CE4EB7E004E87E3 /* Sources */ = { 515 | isa = PBXSourcesBuildPhase; 516 | buildActionMask = 2147483647; 517 | files = ( 518 | DA1A10691D003DFB009F82FA /* Polyline.swift in Sources */, 519 | DA01FB70255361EF00335C7C /* CoreLocation.swift in Sources */, 520 | ); 521 | runOnlyForDeploymentPostprocessing = 0; 522 | }; 523 | 91F783311CE4EB7E004E87E3 /* Sources */ = { 524 | isa = PBXSourcesBuildPhase; 525 | buildActionMask = 2147483647; 526 | files = ( 527 | DA1A106B1D003E56009F82FA /* FunctionalPolylineTests.swift in Sources */, 528 | DA1A106A1D003E56009F82FA /* PolylineTests.swift in Sources */, 529 | ); 530 | runOnlyForDeploymentPostprocessing = 0; 531 | }; 532 | DA1A106C1D003E88009F82FA /* Sources */ = { 533 | isa = PBXSourcesBuildPhase; 534 | buildActionMask = 2147483647; 535 | files = ( 536 | DA1A10891D003EA6009F82FA /* Polyline.swift in Sources */, 537 | DA01FB71255361EF00335C7C /* CoreLocation.swift in Sources */, 538 | ); 539 | runOnlyForDeploymentPostprocessing = 0; 540 | }; 541 | DA1A10761D003E88009F82FA /* Sources */ = { 542 | isa = PBXSourcesBuildPhase; 543 | buildActionMask = 2147483647; 544 | files = ( 545 | DA1A108B1D003EBB009F82FA /* FunctionalPolylineTests.swift in Sources */, 546 | DA1A108A1D003EBB009F82FA /* PolylineTests.swift in Sources */, 547 | ); 548 | runOnlyForDeploymentPostprocessing = 0; 549 | }; 550 | DA1A108C1D00400D009F82FA /* Sources */ = { 551 | isa = PBXSourcesBuildPhase; 552 | buildActionMask = 2147483647; 553 | files = ( 554 | DA1A109A1D004035009F82FA /* Polyline.swift in Sources */, 555 | DA01FB72255361EF00335C7C /* CoreLocation.swift in Sources */, 556 | ); 557 | runOnlyForDeploymentPostprocessing = 0; 558 | }; 559 | /* End PBXSourcesBuildPhase section */ 560 | 561 | /* Begin PBXTargetDependency section */ 562 | 91F783381CE4EB7F004E87E3 /* PBXTargetDependency */ = { 563 | isa = PBXTargetDependency; 564 | target = 91F7832B1CE4EB7E004E87E3 /* PolylineMac */; 565 | targetProxy = 91F783371CE4EB7F004E87E3 /* PBXContainerItemProxy */; 566 | }; 567 | DA1A107D1D003E88009F82FA /* PBXTargetDependency */ = { 568 | isa = PBXTargetDependency; 569 | target = DA1A10701D003E88009F82FA /* PolylineTV */; 570 | targetProxy = DA1A107C1D003E88009F82FA /* PBXContainerItemProxy */; 571 | }; 572 | /* End PBXTargetDependency section */ 573 | 574 | /* Begin XCBuildConfiguration section */ 575 | 207F640F19B5DF7E005261FA /* Debug */ = { 576 | isa = XCBuildConfiguration; 577 | buildSettings = { 578 | ALWAYS_SEARCH_USER_PATHS = NO; 579 | BITCODE_GENERATION_MODE = bitcode; 580 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 581 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 582 | CLANG_CXX_LIBRARY = "libc++"; 583 | CLANG_ENABLE_MODULES = YES; 584 | CLANG_ENABLE_OBJC_ARC = YES; 585 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 586 | CLANG_WARN_BOOL_CONVERSION = YES; 587 | CLANG_WARN_COMMA = YES; 588 | CLANG_WARN_CONSTANT_CONVERSION = YES; 589 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 590 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 591 | CLANG_WARN_EMPTY_BODY = YES; 592 | CLANG_WARN_ENUM_CONVERSION = YES; 593 | CLANG_WARN_INFINITE_RECURSION = YES; 594 | CLANG_WARN_INT_CONVERSION = YES; 595 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 596 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 597 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 598 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 599 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 600 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 601 | CLANG_WARN_STRICT_PROTOTYPES = YES; 602 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 603 | CLANG_WARN_UNREACHABLE_CODE = YES; 604 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 605 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 606 | COPY_PHASE_STRIP = NO; 607 | CURRENT_PROJECT_VERSION = 6; 608 | ENABLE_STRICT_OBJC_MSGSEND = YES; 609 | ENABLE_TESTABILITY = YES; 610 | GCC_C_LANGUAGE_STANDARD = gnu99; 611 | GCC_DYNAMIC_NO_PIC = NO; 612 | GCC_NO_COMMON_BLOCKS = YES; 613 | GCC_OPTIMIZATION_LEVEL = 0; 614 | GCC_PREPROCESSOR_DEFINITIONS = ( 615 | "DEBUG=1", 616 | "$(inherited)", 617 | ); 618 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 619 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 620 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 621 | GCC_WARN_UNDECLARED_SELECTOR = YES; 622 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 623 | GCC_WARN_UNUSED_FUNCTION = YES; 624 | GCC_WARN_UNUSED_VARIABLE = YES; 625 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 626 | MACOSX_DEPLOYMENT_TARGET = 10.14; 627 | MTL_ENABLE_DEBUG_INFO = YES; 628 | ONLY_ACTIVE_ARCH = YES; 629 | SDKROOT = iphoneos; 630 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 631 | SWIFT_VERSION = 5.0; 632 | TARGETED_DEVICE_FAMILY = "1,2"; 633 | TVOS_DEPLOYMENT_TARGET = 12.0; 634 | VERSIONING_SYSTEM = "apple-generic"; 635 | VERSION_INFO_PREFIX = ""; 636 | WATCHOS_DEPLOYMENT_TARGET = 5.0; 637 | }; 638 | name = Debug; 639 | }; 640 | 207F641019B5DF7E005261FA /* Release */ = { 641 | isa = XCBuildConfiguration; 642 | buildSettings = { 643 | ALWAYS_SEARCH_USER_PATHS = NO; 644 | BITCODE_GENERATION_MODE = bitcode; 645 | BUILD_LIBRARY_FOR_DISTRIBUTION = YES; 646 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 647 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 648 | CLANG_CXX_LIBRARY = "libc++"; 649 | CLANG_ENABLE_MODULES = YES; 650 | CLANG_ENABLE_OBJC_ARC = YES; 651 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 652 | CLANG_WARN_BOOL_CONVERSION = YES; 653 | CLANG_WARN_COMMA = YES; 654 | CLANG_WARN_CONSTANT_CONVERSION = YES; 655 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 656 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 657 | CLANG_WARN_EMPTY_BODY = YES; 658 | CLANG_WARN_ENUM_CONVERSION = YES; 659 | CLANG_WARN_INFINITE_RECURSION = YES; 660 | CLANG_WARN_INT_CONVERSION = YES; 661 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 662 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 663 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 664 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 665 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 666 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 667 | CLANG_WARN_STRICT_PROTOTYPES = YES; 668 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 669 | CLANG_WARN_UNREACHABLE_CODE = YES; 670 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 671 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 672 | COPY_PHASE_STRIP = YES; 673 | CURRENT_PROJECT_VERSION = 6; 674 | ENABLE_NS_ASSERTIONS = NO; 675 | ENABLE_STRICT_OBJC_MSGSEND = YES; 676 | GCC_C_LANGUAGE_STANDARD = gnu99; 677 | GCC_NO_COMMON_BLOCKS = YES; 678 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 679 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 680 | GCC_WARN_UNDECLARED_SELECTOR = YES; 681 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 682 | GCC_WARN_UNUSED_FUNCTION = YES; 683 | GCC_WARN_UNUSED_VARIABLE = YES; 684 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 685 | MACOSX_DEPLOYMENT_TARGET = 10.14; 686 | MTL_ENABLE_DEBUG_INFO = NO; 687 | SDKROOT = iphoneos; 688 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 689 | SWIFT_VERSION = 5.0; 690 | TARGETED_DEVICE_FAMILY = "1,2"; 691 | TVOS_DEPLOYMENT_TARGET = 12.0; 692 | VALIDATE_PRODUCT = YES; 693 | VERSIONING_SYSTEM = "apple-generic"; 694 | VERSION_INFO_PREFIX = ""; 695 | WATCHOS_DEPLOYMENT_TARGET = 5.0; 696 | }; 697 | name = Release; 698 | }; 699 | 207F641219B5DF7E005261FA /* Debug */ = { 700 | isa = XCBuildConfiguration; 701 | buildSettings = { 702 | APPLICATION_EXTENSION_API_ONLY = YES; 703 | CLANG_ENABLE_MODULES = YES; 704 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 705 | DEFINES_MODULE = YES; 706 | DYLIB_COMPATIBILITY_VERSION = 1; 707 | DYLIB_CURRENT_VERSION = 7; 708 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 709 | EXCLUDED_ARCHS = ""; 710 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 711 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 712 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 713 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 714 | PRODUCT_BUNDLE_IDENTIFIER = "com.ramoapps.$(PRODUCT_NAME:rfc1034identifier)"; 715 | PRODUCT_NAME = "$(TARGET_NAME)"; 716 | SKIP_INSTALL = YES; 717 | SWIFT_OBJC_BRIDGING_HEADER = ""; 718 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 719 | }; 720 | name = Debug; 721 | }; 722 | 207F641319B5DF7E005261FA /* Release */ = { 723 | isa = XCBuildConfiguration; 724 | buildSettings = { 725 | APPLICATION_EXTENSION_API_ONLY = YES; 726 | CLANG_ENABLE_MODULES = YES; 727 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 728 | DEFINES_MODULE = YES; 729 | DYLIB_COMPATIBILITY_VERSION = 1; 730 | DYLIB_CURRENT_VERSION = 7; 731 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 732 | EXCLUDED_ARCHS = ""; 733 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 734 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 735 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 736 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 737 | PRODUCT_BUNDLE_IDENTIFIER = "com.ramoapps.$(PRODUCT_NAME:rfc1034identifier)"; 738 | PRODUCT_NAME = "$(TARGET_NAME)"; 739 | SKIP_INSTALL = YES; 740 | SWIFT_OBJC_BRIDGING_HEADER = ""; 741 | }; 742 | name = Release; 743 | }; 744 | 207F641519B5DF7E005261FA /* Debug */ = { 745 | isa = XCBuildConfiguration; 746 | buildSettings = { 747 | GCC_PREPROCESSOR_DEFINITIONS = ( 748 | "DEBUG=1", 749 | "$(inherited)", 750 | ); 751 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 752 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 753 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 754 | PRODUCT_BUNDLE_IDENTIFIER = "com.ramoapps.$(PRODUCT_NAME:rfc1034identifier)"; 755 | PRODUCT_NAME = "$(TARGET_NAME)"; 756 | }; 757 | name = Debug; 758 | }; 759 | 207F641619B5DF7E005261FA /* Release */ = { 760 | isa = XCBuildConfiguration; 761 | buildSettings = { 762 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 763 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 764 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 765 | PRODUCT_BUNDLE_IDENTIFIER = "com.ramoapps.$(PRODUCT_NAME:rfc1034identifier)"; 766 | PRODUCT_NAME = "$(TARGET_NAME)"; 767 | }; 768 | name = Release; 769 | }; 770 | 91F7833E1CE4EB7F004E87E3 /* Debug */ = { 771 | isa = XCBuildConfiguration; 772 | buildSettings = { 773 | CLANG_ANALYZER_NONNULL = YES; 774 | CODE_SIGN_IDENTITY = ""; 775 | COMBINE_HIDPI_IMAGES = YES; 776 | DEAD_CODE_STRIPPING = YES; 777 | DEBUG_INFORMATION_FORMAT = dwarf; 778 | DEFINES_MODULE = YES; 779 | DYLIB_COMPATIBILITY_VERSION = 1; 780 | DYLIB_CURRENT_VERSION = 7; 781 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 782 | FRAMEWORK_VERSION = A; 783 | GCC_NO_COMMON_BLOCKS = YES; 784 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 785 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 786 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 787 | MACOSX_DEPLOYMENT_TARGET = 10.14; 788 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 789 | PRODUCT_NAME = Polyline; 790 | SDKROOT = macosx; 791 | SKIP_INSTALL = YES; 792 | }; 793 | name = Debug; 794 | }; 795 | 91F7833F1CE4EB7F004E87E3 /* Release */ = { 796 | isa = XCBuildConfiguration; 797 | buildSettings = { 798 | CLANG_ANALYZER_NONNULL = YES; 799 | CODE_SIGN_IDENTITY = ""; 800 | COMBINE_HIDPI_IMAGES = YES; 801 | COPY_PHASE_STRIP = NO; 802 | DEAD_CODE_STRIPPING = YES; 803 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 804 | DEFINES_MODULE = YES; 805 | DYLIB_COMPATIBILITY_VERSION = 1; 806 | DYLIB_CURRENT_VERSION = 7; 807 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 808 | FRAMEWORK_VERSION = A; 809 | GCC_NO_COMMON_BLOCKS = YES; 810 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 811 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 812 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 813 | MACOSX_DEPLOYMENT_TARGET = 10.14; 814 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 815 | PRODUCT_NAME = Polyline; 816 | SDKROOT = macosx; 817 | SKIP_INSTALL = YES; 818 | }; 819 | name = Release; 820 | }; 821 | 91F783411CE4EB7F004E87E3 /* Debug */ = { 822 | isa = XCBuildConfiguration; 823 | buildSettings = { 824 | CLANG_ANALYZER_NONNULL = YES; 825 | CODE_SIGN_IDENTITY = "-"; 826 | COMBINE_HIDPI_IMAGES = YES; 827 | DEAD_CODE_STRIPPING = YES; 828 | DEBUG_INFORMATION_FORMAT = dwarf; 829 | GCC_NO_COMMON_BLOCKS = YES; 830 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 831 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 832 | MACOSX_DEPLOYMENT_TARGET = 10.14; 833 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.PolylineTests; 834 | PRODUCT_NAME = PolylineTests; 835 | SDKROOT = macosx; 836 | }; 837 | name = Debug; 838 | }; 839 | 91F783421CE4EB7F004E87E3 /* Release */ = { 840 | isa = XCBuildConfiguration; 841 | buildSettings = { 842 | CLANG_ANALYZER_NONNULL = YES; 843 | CODE_SIGN_IDENTITY = "-"; 844 | COMBINE_HIDPI_IMAGES = YES; 845 | COPY_PHASE_STRIP = NO; 846 | DEAD_CODE_STRIPPING = YES; 847 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 848 | GCC_NO_COMMON_BLOCKS = YES; 849 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 850 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 851 | MACOSX_DEPLOYMENT_TARGET = 10.14; 852 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.PolylineTests; 853 | PRODUCT_NAME = PolylineTests; 854 | SDKROOT = macosx; 855 | }; 856 | name = Release; 857 | }; 858 | DA1A10821D003E88009F82FA /* Debug */ = { 859 | isa = XCBuildConfiguration; 860 | buildSettings = { 861 | CLANG_ANALYZER_NONNULL = YES; 862 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 863 | DEBUG_INFORMATION_FORMAT = dwarf; 864 | DEFINES_MODULE = YES; 865 | DYLIB_COMPATIBILITY_VERSION = 1; 866 | DYLIB_CURRENT_VERSION = 7; 867 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 868 | GCC_NO_COMMON_BLOCKS = YES; 869 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 870 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 871 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 872 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 873 | PRODUCT_NAME = Polyline; 874 | SDKROOT = appletvos; 875 | SKIP_INSTALL = YES; 876 | TARGETED_DEVICE_FAMILY = 3; 877 | TVOS_DEPLOYMENT_TARGET = 12.0; 878 | }; 879 | name = Debug; 880 | }; 881 | DA1A10831D003E88009F82FA /* Release */ = { 882 | isa = XCBuildConfiguration; 883 | buildSettings = { 884 | CLANG_ANALYZER_NONNULL = YES; 885 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 886 | COPY_PHASE_STRIP = NO; 887 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 888 | DEFINES_MODULE = YES; 889 | DYLIB_COMPATIBILITY_VERSION = 1; 890 | DYLIB_CURRENT_VERSION = 7; 891 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 892 | GCC_NO_COMMON_BLOCKS = YES; 893 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 894 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 895 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 896 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 897 | PRODUCT_NAME = Polyline; 898 | SDKROOT = appletvos; 899 | SKIP_INSTALL = YES; 900 | TARGETED_DEVICE_FAMILY = 3; 901 | TVOS_DEPLOYMENT_TARGET = 12.0; 902 | }; 903 | name = Release; 904 | }; 905 | DA1A10841D003E88009F82FA /* Debug */ = { 906 | isa = XCBuildConfiguration; 907 | buildSettings = { 908 | CLANG_ANALYZER_NONNULL = YES; 909 | DEBUG_INFORMATION_FORMAT = dwarf; 910 | GCC_NO_COMMON_BLOCKS = YES; 911 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 912 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 913 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.PolylineTests; 914 | PRODUCT_NAME = PolylineTests; 915 | SDKROOT = appletvos; 916 | TVOS_DEPLOYMENT_TARGET = 12.0; 917 | }; 918 | name = Debug; 919 | }; 920 | DA1A10851D003E88009F82FA /* Release */ = { 921 | isa = XCBuildConfiguration; 922 | buildSettings = { 923 | CLANG_ANALYZER_NONNULL = YES; 924 | COPY_PHASE_STRIP = NO; 925 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 926 | GCC_NO_COMMON_BLOCKS = YES; 927 | INFOPLIST_FILE = Tests/PolylineTests/Info.plist; 928 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 929 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.PolylineTests; 930 | PRODUCT_NAME = PolylineTests; 931 | SDKROOT = appletvos; 932 | TVOS_DEPLOYMENT_TARGET = 12.0; 933 | }; 934 | name = Release; 935 | }; 936 | DA1A10971D00400D009F82FA /* Debug */ = { 937 | isa = XCBuildConfiguration; 938 | buildSettings = { 939 | APPLICATION_EXTENSION_API_ONLY = YES; 940 | CLANG_ANALYZER_NONNULL = YES; 941 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 942 | DEBUG_INFORMATION_FORMAT = dwarf; 943 | DEFINES_MODULE = YES; 944 | DYLIB_COMPATIBILITY_VERSION = 1; 945 | DYLIB_CURRENT_VERSION = 7; 946 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 947 | GCC_NO_COMMON_BLOCKS = YES; 948 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 949 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 950 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 951 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 952 | PRODUCT_NAME = Polyline; 953 | SDKROOT = watchos; 954 | SKIP_INSTALL = YES; 955 | TARGETED_DEVICE_FAMILY = 4; 956 | WATCHOS_DEPLOYMENT_TARGET = 5.0; 957 | }; 958 | name = Debug; 959 | }; 960 | DA1A10981D00400D009F82FA /* Release */ = { 961 | isa = XCBuildConfiguration; 962 | buildSettings = { 963 | APPLICATION_EXTENSION_API_ONLY = YES; 964 | CLANG_ANALYZER_NONNULL = YES; 965 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 966 | COPY_PHASE_STRIP = NO; 967 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 968 | DEFINES_MODULE = YES; 969 | DYLIB_COMPATIBILITY_VERSION = 1; 970 | DYLIB_CURRENT_VERSION = 7; 971 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 972 | GCC_NO_COMMON_BLOCKS = YES; 973 | INFOPLIST_FILE = Sources/Polyline/Info.plist; 974 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 975 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 976 | PRODUCT_BUNDLE_IDENTIFIER = com.ramoapps.Polyline; 977 | PRODUCT_NAME = Polyline; 978 | SDKROOT = watchos; 979 | SKIP_INSTALL = YES; 980 | TARGETED_DEVICE_FAMILY = 4; 981 | WATCHOS_DEPLOYMENT_TARGET = 5.0; 982 | }; 983 | name = Release; 984 | }; 985 | /* End XCBuildConfiguration section */ 986 | 987 | /* Begin XCConfigurationList section */ 988 | 207F63F819B5DF7E005261FA /* Build configuration list for PBXProject "Polyline" */ = { 989 | isa = XCConfigurationList; 990 | buildConfigurations = ( 991 | 207F640F19B5DF7E005261FA /* Debug */, 992 | 207F641019B5DF7E005261FA /* Release */, 993 | ); 994 | defaultConfigurationIsVisible = 0; 995 | defaultConfigurationName = Release; 996 | }; 997 | 207F641119B5DF7E005261FA /* Build configuration list for PBXNativeTarget "Polyline" */ = { 998 | isa = XCConfigurationList; 999 | buildConfigurations = ( 1000 | 207F641219B5DF7E005261FA /* Debug */, 1001 | 207F641319B5DF7E005261FA /* Release */, 1002 | ); 1003 | defaultConfigurationIsVisible = 0; 1004 | defaultConfigurationName = Release; 1005 | }; 1006 | 207F641419B5DF7E005261FA /* Build configuration list for PBXNativeTarget "PolylineTests" */ = { 1007 | isa = XCConfigurationList; 1008 | buildConfigurations = ( 1009 | 207F641519B5DF7E005261FA /* Debug */, 1010 | 207F641619B5DF7E005261FA /* Release */, 1011 | ); 1012 | defaultConfigurationIsVisible = 0; 1013 | defaultConfigurationName = Release; 1014 | }; 1015 | 91F7833D1CE4EB7F004E87E3 /* Build configuration list for PBXNativeTarget "PolylineMac" */ = { 1016 | isa = XCConfigurationList; 1017 | buildConfigurations = ( 1018 | 91F7833E1CE4EB7F004E87E3 /* Debug */, 1019 | 91F7833F1CE4EB7F004E87E3 /* Release */, 1020 | ); 1021 | defaultConfigurationIsVisible = 0; 1022 | defaultConfigurationName = Release; 1023 | }; 1024 | 91F783401CE4EB7F004E87E3 /* Build configuration list for PBXNativeTarget "PolylineMacTests" */ = { 1025 | isa = XCConfigurationList; 1026 | buildConfigurations = ( 1027 | 91F783411CE4EB7F004E87E3 /* Debug */, 1028 | 91F783421CE4EB7F004E87E3 /* Release */, 1029 | ); 1030 | defaultConfigurationIsVisible = 0; 1031 | defaultConfigurationName = Release; 1032 | }; 1033 | DA1A10861D003E88009F82FA /* Build configuration list for PBXNativeTarget "PolylineTV" */ = { 1034 | isa = XCConfigurationList; 1035 | buildConfigurations = ( 1036 | DA1A10821D003E88009F82FA /* Debug */, 1037 | DA1A10831D003E88009F82FA /* Release */, 1038 | ); 1039 | defaultConfigurationIsVisible = 0; 1040 | defaultConfigurationName = Release; 1041 | }; 1042 | DA1A10871D003E88009F82FA /* Build configuration list for PBXNativeTarget "PolylineTVTests" */ = { 1043 | isa = XCConfigurationList; 1044 | buildConfigurations = ( 1045 | DA1A10841D003E88009F82FA /* Debug */, 1046 | DA1A10851D003E88009F82FA /* Release */, 1047 | ); 1048 | defaultConfigurationIsVisible = 0; 1049 | defaultConfigurationName = Release; 1050 | }; 1051 | DA1A10961D00400D009F82FA /* Build configuration list for PBXNativeTarget "PolylineWatch" */ = { 1052 | isa = XCConfigurationList; 1053 | buildConfigurations = ( 1054 | DA1A10971D00400D009F82FA /* Debug */, 1055 | DA1A10981D00400D009F82FA /* Release */, 1056 | ); 1057 | defaultConfigurationIsVisible = 0; 1058 | defaultConfigurationName = Release; 1059 | }; 1060 | /* End XCConfigurationList section */ 1061 | }; 1062 | rootObject = 207F63F519B5DF7E005261FA /* Project object */; 1063 | } 1064 | --------------------------------------------------------------------------------