├── .gitignore ├── Compass.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── LICENSE ├── README.md ├── compass ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-167.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-72.png │ │ ├── Icon-72@2x.png │ │ ├── Icon-76.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-Small-40.png │ │ ├── Icon-Small-40@2x.png │ │ ├── Icon-Small-40@3x.png │ │ ├── Icon-Small-50.png │ │ ├── Icon-Small-50@2x.png │ │ ├── Icon-Small.png │ │ ├── Icon-Small@2x.png │ │ ├── Icon-Small@3x.png │ │ ├── Icon.png │ │ └── Icon@2x.png │ ├── Contents.json │ └── arrow.imageset │ │ ├── Contents.json │ │ └── Icon.jpg ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CLLocation+Extension.swift ├── CompassViewController.swift ├── Info.plist ├── LocationDelegate.swift ├── MapViewController.swift ├── MapViewControllerDelegate.swift └── UserDefauts+Extensions.swift └── logo.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | *.DS_Store 6 | 7 | ## Build generated 8 | build/ 9 | DerivedData/ 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xcuserstate 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /Compass.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 647284251EB38CE9002474A2 /* UserDefauts+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647284241EB38CE9002474A2 /* UserDefauts+Extensions.swift */; }; 11 | 64BE1FD81EAC8E23009A00B6 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BE1FD71EAC8E23009A00B6 /* MapViewController.swift */; }; 12 | 64BE1FDA1EAC9217009A00B6 /* MapViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BE1FD91EAC9217009A00B6 /* MapViewControllerDelegate.swift */; }; 13 | 64E8BF6C1E9535A200B10108 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E8BF6B1E9535A200B10108 /* AppDelegate.swift */; }; 14 | 64E8BF6E1E9535A200B10108 /* CompassViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E8BF6D1E9535A200B10108 /* CompassViewController.swift */; }; 15 | 64E8BF711E9535A200B10108 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64E8BF6F1E9535A200B10108 /* Main.storyboard */; }; 16 | 64E8BF731E9535A200B10108 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 64E8BF721E9535A200B10108 /* Assets.xcassets */; }; 17 | 64E8BF761E9535A200B10108 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64E8BF741E9535A200B10108 /* LaunchScreen.storyboard */; }; 18 | 64E8BF7E1E953A6200B10108 /* LocationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E8BF7D1E953A6200B10108 /* LocationDelegate.swift */; }; 19 | 64E8BF801E953ACC00B10108 /* CLLocation+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E8BF7F1E953ACC00B10108 /* CLLocation+Extension.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 647284241EB38CE9002474A2 /* UserDefauts+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefauts+Extensions.swift"; sourceTree = ""; }; 24 | 64BE1FD71EAC8E23009A00B6 /* MapViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = ""; }; 25 | 64BE1FD91EAC9217009A00B6 /* MapViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewControllerDelegate.swift; sourceTree = ""; }; 26 | 64E8BF681E9535A200B10108 /* compass.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = compass.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 64E8BF6B1E9535A200B10108 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 28 | 64E8BF6D1E9535A200B10108 /* CompassViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompassViewController.swift; sourceTree = ""; }; 29 | 64E8BF701E9535A200B10108 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 64E8BF721E9535A200B10108 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 64E8BF751E9535A200B10108 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 64E8BF771E9535A200B10108 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 64E8BF7D1E953A6200B10108 /* LocationDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationDelegate.swift; sourceTree = ""; }; 34 | 64E8BF7F1E953ACC00B10108 /* CLLocation+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CLLocation+Extension.swift"; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 64E8BF651E9535A200B10108 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 64E8BF5F1E9535A200B10108 = { 49 | isa = PBXGroup; 50 | children = ( 51 | 64E8BF6A1E9535A200B10108 /* compass */, 52 | 64E8BF691E9535A200B10108 /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 64E8BF691E9535A200B10108 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 64E8BF681E9535A200B10108 /* compass.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 64E8BF6A1E9535A200B10108 /* compass */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 64BE1FD71EAC8E23009A00B6 /* MapViewController.swift */, 68 | 64BE1FD91EAC9217009A00B6 /* MapViewControllerDelegate.swift */, 69 | 64E8BF6B1E9535A200B10108 /* AppDelegate.swift */, 70 | 64E8BF6D1E9535A200B10108 /* CompassViewController.swift */, 71 | 647284241EB38CE9002474A2 /* UserDefauts+Extensions.swift */, 72 | 64E8BF7D1E953A6200B10108 /* LocationDelegate.swift */, 73 | 64E8BF7F1E953ACC00B10108 /* CLLocation+Extension.swift */, 74 | 64E8BF6F1E9535A200B10108 /* Main.storyboard */, 75 | 64E8BF721E9535A200B10108 /* Assets.xcassets */, 76 | 64E8BF741E9535A200B10108 /* LaunchScreen.storyboard */, 77 | 64E8BF771E9535A200B10108 /* Info.plist */, 78 | ); 79 | path = compass; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 64E8BF671E9535A200B10108 /* compass */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 64E8BF7A1E9535A200B10108 /* Build configuration list for PBXNativeTarget "compass" */; 88 | buildPhases = ( 89 | 64E8BF641E9535A200B10108 /* Sources */, 90 | 64E8BF651E9535A200B10108 /* Frameworks */, 91 | 64E8BF661E9535A200B10108 /* Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = compass; 98 | productName = compass; 99 | productReference = 64E8BF681E9535A200B10108 /* compass.app */; 100 | productType = "com.apple.product-type.application"; 101 | }; 102 | /* End PBXNativeTarget section */ 103 | 104 | /* Begin PBXProject section */ 105 | 64E8BF601E9535A200B10108 /* Project object */ = { 106 | isa = PBXProject; 107 | attributes = { 108 | LastSwiftUpdateCheck = 0830; 109 | LastUpgradeCheck = 0830; 110 | ORGANIZATIONNAME = "Kimchi Media"; 111 | TargetAttributes = { 112 | 64E8BF671E9535A200B10108 = { 113 | CreatedOnToolsVersion = 8.3; 114 | DevelopmentTeam = 5HP4VS26CA; 115 | ProvisioningStyle = Automatic; 116 | }; 117 | }; 118 | }; 119 | buildConfigurationList = 64E8BF631E9535A200B10108 /* Build configuration list for PBXProject "Compass" */; 120 | compatibilityVersion = "Xcode 3.2"; 121 | developmentRegion = English; 122 | hasScannedForEncodings = 0; 123 | knownRegions = ( 124 | en, 125 | Base, 126 | ); 127 | mainGroup = 64E8BF5F1E9535A200B10108; 128 | productRefGroup = 64E8BF691E9535A200B10108 /* Products */; 129 | projectDirPath = ""; 130 | projectRoot = ""; 131 | targets = ( 132 | 64E8BF671E9535A200B10108 /* compass */, 133 | ); 134 | }; 135 | /* End PBXProject section */ 136 | 137 | /* Begin PBXResourcesBuildPhase section */ 138 | 64E8BF661E9535A200B10108 /* Resources */ = { 139 | isa = PBXResourcesBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | 64E8BF761E9535A200B10108 /* LaunchScreen.storyboard in Resources */, 143 | 64E8BF731E9535A200B10108 /* Assets.xcassets in Resources */, 144 | 64E8BF711E9535A200B10108 /* Main.storyboard in Resources */, 145 | ); 146 | runOnlyForDeploymentPostprocessing = 0; 147 | }; 148 | /* End PBXResourcesBuildPhase section */ 149 | 150 | /* Begin PBXSourcesBuildPhase section */ 151 | 64E8BF641E9535A200B10108 /* Sources */ = { 152 | isa = PBXSourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | 64E8BF6E1E9535A200B10108 /* CompassViewController.swift in Sources */, 156 | 64E8BF801E953ACC00B10108 /* CLLocation+Extension.swift in Sources */, 157 | 64BE1FDA1EAC9217009A00B6 /* MapViewControllerDelegate.swift in Sources */, 158 | 647284251EB38CE9002474A2 /* UserDefauts+Extensions.swift in Sources */, 159 | 64E8BF7E1E953A6200B10108 /* LocationDelegate.swift in Sources */, 160 | 64BE1FD81EAC8E23009A00B6 /* MapViewController.swift in Sources */, 161 | 64E8BF6C1E9535A200B10108 /* AppDelegate.swift in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin PBXVariantGroup section */ 168 | 64E8BF6F1E9535A200B10108 /* Main.storyboard */ = { 169 | isa = PBXVariantGroup; 170 | children = ( 171 | 64E8BF701E9535A200B10108 /* Base */, 172 | ); 173 | name = Main.storyboard; 174 | sourceTree = ""; 175 | }; 176 | 64E8BF741E9535A200B10108 /* LaunchScreen.storyboard */ = { 177 | isa = PBXVariantGroup; 178 | children = ( 179 | 64E8BF751E9535A200B10108 /* Base */, 180 | ); 181 | name = LaunchScreen.storyboard; 182 | sourceTree = ""; 183 | }; 184 | /* End PBXVariantGroup section */ 185 | 186 | /* Begin XCBuildConfiguration section */ 187 | 64E8BF781E9535A200B10108 /* Debug */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_ANALYZER_NONNULL = YES; 192 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 193 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 194 | CLANG_CXX_LIBRARY = "libc++"; 195 | CLANG_ENABLE_MODULES = YES; 196 | CLANG_ENABLE_OBJC_ARC = YES; 197 | CLANG_WARN_BOOL_CONVERSION = YES; 198 | CLANG_WARN_CONSTANT_CONVERSION = YES; 199 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 200 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 201 | CLANG_WARN_EMPTY_BODY = YES; 202 | CLANG_WARN_ENUM_CONVERSION = YES; 203 | CLANG_WARN_INFINITE_RECURSION = YES; 204 | CLANG_WARN_INT_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 207 | CLANG_WARN_UNREACHABLE_CODE = YES; 208 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 209 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 210 | COPY_PHASE_STRIP = NO; 211 | DEBUG_INFORMATION_FORMAT = dwarf; 212 | ENABLE_STRICT_OBJC_MSGSEND = YES; 213 | ENABLE_TESTABILITY = YES; 214 | GCC_C_LANGUAGE_STANDARD = gnu99; 215 | GCC_DYNAMIC_NO_PIC = NO; 216 | GCC_NO_COMMON_BLOCKS = YES; 217 | GCC_OPTIMIZATION_LEVEL = 0; 218 | GCC_PREPROCESSOR_DEFINITIONS = ( 219 | "DEBUG=1", 220 | "$(inherited)", 221 | ); 222 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 223 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 224 | GCC_WARN_UNDECLARED_SELECTOR = YES; 225 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 226 | GCC_WARN_UNUSED_FUNCTION = YES; 227 | GCC_WARN_UNUSED_VARIABLE = YES; 228 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 229 | MTL_ENABLE_DEBUG_INFO = YES; 230 | ONLY_ACTIVE_ARCH = YES; 231 | SDKROOT = iphoneos; 232 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 233 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 234 | TARGETED_DEVICE_FAMILY = "1,2"; 235 | }; 236 | name = Debug; 237 | }; 238 | 64E8BF791E9535A200B10108 /* Release */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_ANALYZER_NONNULL = YES; 243 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BOOL_CONVERSION = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 251 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 252 | CLANG_WARN_EMPTY_BODY = YES; 253 | CLANG_WARN_ENUM_CONVERSION = YES; 254 | CLANG_WARN_INFINITE_RECURSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu99; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | SDKROOT = iphoneos; 276 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 277 | TARGETED_DEVICE_FAMILY = "1,2"; 278 | VALIDATE_PRODUCT = YES; 279 | }; 280 | name = Release; 281 | }; 282 | 64E8BF7B1E9535A200B10108 /* Debug */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 286 | DEVELOPMENT_TEAM = 5HP4VS26CA; 287 | INFOPLIST_FILE = compass/Info.plist; 288 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 290 | PRODUCT_BUNDLE_IDENTIFIER = media.kimchi.compass; 291 | PRODUCT_NAME = "$(TARGET_NAME)"; 292 | SWIFT_VERSION = 3.0; 293 | }; 294 | name = Debug; 295 | }; 296 | 64E8BF7C1E9535A200B10108 /* Release */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | DEVELOPMENT_TEAM = 5HP4VS26CA; 301 | INFOPLIST_FILE = compass/Info.plist; 302 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 303 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 304 | PRODUCT_BUNDLE_IDENTIFIER = media.kimchi.compass; 305 | PRODUCT_NAME = "$(TARGET_NAME)"; 306 | SWIFT_VERSION = 3.0; 307 | }; 308 | name = Release; 309 | }; 310 | /* End XCBuildConfiguration section */ 311 | 312 | /* Begin XCConfigurationList section */ 313 | 64E8BF631E9535A200B10108 /* Build configuration list for PBXProject "Compass" */ = { 314 | isa = XCConfigurationList; 315 | buildConfigurations = ( 316 | 64E8BF781E9535A200B10108 /* Debug */, 317 | 64E8BF791E9535A200B10108 /* Release */, 318 | ); 319 | defaultConfigurationIsVisible = 0; 320 | defaultConfigurationName = Release; 321 | }; 322 | 64E8BF7A1E9535A200B10108 /* Build configuration list for PBXNativeTarget "compass" */ = { 323 | isa = XCConfigurationList; 324 | buildConfigurations = ( 325 | 64E8BF7B1E9535A200B10108 /* Debug */, 326 | 64E8BF7C1E9535A200B10108 /* Release */, 327 | ); 328 | defaultConfigurationIsVisible = 0; 329 | defaultConfigurationName = Release; 330 | }; 331 | /* End XCConfigurationList section */ 332 | }; 333 | rootObject = 64E8BF601E9535A200B10108 /* Project object */; 334 | } 335 | -------------------------------------------------------------------------------- /Compass.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Federico Zanetello 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Swift Web Crawler in action 3 |

4 | 5 | # Compass 6 | 7 | Welcome to Compass! A minimal Compass iOS App. 8 | 9 | To know more about the App, please refer to my blog [here](https://www.fivestars.blog/code/build-compass-app-swift.html). 10 | 11 | ## How to build the App 12 | 1. Install the latest [Xcode developer tools](https://developer.apple.com/xcode/downloads/) from Apple. 13 | 2. Clone the repository: `$ git clone https://github.com/zntfdr/Compass` 14 | 3. Open `Compass.xcodeproj` in Xcode. 15 | 4. Build the `compass` scheme in Xcode. 16 | 5. Enjoy! 🚀 17 | 18 | ## Author 19 | [Federico Zanetello](https://github.com/zntfdr) ([@zntfdr](https://twitter.com/zntfdr)) 20 | 21 | 22 | -------------------------------------------------------------------------------- /compass/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 05/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "size" : "29x29", 15 | "idiom" : "iphone", 16 | "filename" : "Icon-Small.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "iphone", 22 | "filename" : "Icon-Small@2x.png", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "size" : "29x29", 27 | "idiom" : "iphone", 28 | "filename" : "Icon-Small@3x.png", 29 | "scale" : "3x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "iphone", 34 | "filename" : "Icon-Small-40@2x.png", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "size" : "40x40", 39 | "idiom" : "iphone", 40 | "filename" : "Icon-Small-40@3x.png", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "size" : "57x57", 45 | "idiom" : "iphone", 46 | "filename" : "Icon.png", 47 | "scale" : "1x" 48 | }, 49 | { 50 | "size" : "57x57", 51 | "idiom" : "iphone", 52 | "filename" : "Icon@2x.png", 53 | "scale" : "2x" 54 | }, 55 | { 56 | "size" : "60x60", 57 | "idiom" : "iphone", 58 | "filename" : "Icon-60@2x.png", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "size" : "60x60", 63 | "idiom" : "iphone", 64 | "filename" : "Icon-60@3x.png", 65 | "scale" : "3x" 66 | }, 67 | { 68 | "idiom" : "ipad", 69 | "size" : "20x20", 70 | "scale" : "1x" 71 | }, 72 | { 73 | "idiom" : "ipad", 74 | "size" : "20x20", 75 | "scale" : "2x" 76 | }, 77 | { 78 | "size" : "29x29", 79 | "idiom" : "ipad", 80 | "filename" : "Icon-Small.png", 81 | "scale" : "1x" 82 | }, 83 | { 84 | "size" : "29x29", 85 | "idiom" : "ipad", 86 | "filename" : "Icon-Small@2x.png", 87 | "scale" : "2x" 88 | }, 89 | { 90 | "size" : "40x40", 91 | "idiom" : "ipad", 92 | "filename" : "Icon-Small-40.png", 93 | "scale" : "1x" 94 | }, 95 | { 96 | "size" : "40x40", 97 | "idiom" : "ipad", 98 | "filename" : "Icon-Small-40@2x.png", 99 | "scale" : "2x" 100 | }, 101 | { 102 | "size" : "50x50", 103 | "idiom" : "ipad", 104 | "filename" : "Icon-Small-50.png", 105 | "scale" : "1x" 106 | }, 107 | { 108 | "size" : "50x50", 109 | "idiom" : "ipad", 110 | "filename" : "Icon-Small-50@2x.png", 111 | "scale" : "2x" 112 | }, 113 | { 114 | "size" : "72x72", 115 | "idiom" : "ipad", 116 | "filename" : "Icon-72.png", 117 | "scale" : "1x" 118 | }, 119 | { 120 | "size" : "72x72", 121 | "idiom" : "ipad", 122 | "filename" : "Icon-72@2x.png", 123 | "scale" : "2x" 124 | }, 125 | { 126 | "size" : "76x76", 127 | "idiom" : "ipad", 128 | "filename" : "Icon-76.png", 129 | "scale" : "1x" 130 | }, 131 | { 132 | "size" : "76x76", 133 | "idiom" : "ipad", 134 | "filename" : "Icon-76@2x.png", 135 | "scale" : "2x" 136 | }, 137 | { 138 | "size" : "83.5x83.5", 139 | "idiom" : "ipad", 140 | "filename" : "Icon-167.png", 141 | "scale" : "2x" 142 | } 143 | ], 144 | "info" : { 145 | "version" : 1, 146 | "author" : "xcode" 147 | } 148 | } -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-167.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /compass/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /compass/Assets.xcassets/arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Icon.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /compass/Assets.xcassets/arrow.imageset/Icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/compass/Assets.xcassets/arrow.imageset/Icon.jpg -------------------------------------------------------------------------------- /compass/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /compass/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /compass/CLLocation+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CLLocation+Extension.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 05/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | import UIKit 12 | 13 | public extension CLLocation { 14 | func bearingToLocationRadian(_ destinationLocation: CLLocation) -> CGFloat { 15 | 16 | let lat1 = self.coordinate.latitude.degreesToRadians 17 | let lon1 = self.coordinate.longitude.degreesToRadians 18 | 19 | let lat2 = destinationLocation.coordinate.latitude.degreesToRadians 20 | let lon2 = destinationLocation.coordinate.longitude.degreesToRadians 21 | 22 | let dLon = lon2 - lon1 23 | 24 | let y = sin(dLon) * cos(lat2) 25 | let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon) 26 | let radiansBearing = atan2(y, x) 27 | 28 | return CGFloat(radiansBearing) 29 | } 30 | 31 | func bearingToLocationDegrees(destinationLocation: CLLocation) -> CGFloat { 32 | return bearingToLocationRadian(destinationLocation).radiansToDegrees 33 | } 34 | } 35 | 36 | extension CGFloat { 37 | var degreesToRadians: CGFloat { return self * .pi / 180 } 38 | var radiansToDegrees: CGFloat { return self * 180 / .pi } 39 | } 40 | 41 | private extension Double { 42 | var degreesToRadians: Double { return Double(CGFloat(self).degreesToRadians) } 43 | var radiansToDegrees: Double { return Double(CGFloat(self).radiansToDegrees) } 44 | } 45 | -------------------------------------------------------------------------------- /compass/CompassViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CompassViewController.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 05/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CoreLocation 11 | 12 | class CompassViewController: UIViewController { 13 | @IBOutlet weak var imageView: UIImageView! 14 | 15 | let locationDelegate = LocationDelegate() 16 | var latestLocation: CLLocation? = nil 17 | var yourLocationBearing: CGFloat { return latestLocation?.bearingToLocationRadian(self.yourLocation) ?? 0 } 18 | var yourLocation: CLLocation { 19 | get { return UserDefaults.standard.currentLocation } 20 | set { UserDefaults.standard.currentLocation = newValue } 21 | } 22 | 23 | let locationManager: CLLocationManager = { 24 | $0.requestWhenInUseAuthorization() 25 | $0.desiredAccuracy = kCLLocationAccuracyBest 26 | $0.startUpdatingLocation() 27 | $0.startUpdatingHeading() 28 | return $0 29 | }(CLLocationManager()) 30 | 31 | private func orientationAdjustment() -> CGFloat { 32 | let isFaceDown: Bool = { 33 | switch UIDevice.current.orientation { 34 | case .faceDown: return true 35 | default: return false 36 | } 37 | }() 38 | 39 | let adjAngle: CGFloat = { 40 | switch UIApplication.shared.statusBarOrientation { 41 | case .landscapeLeft: return 90 42 | case .landscapeRight: return -90 43 | case .portrait, .unknown: return 0 44 | case .portraitUpsideDown: return isFaceDown ? 180 : -180 45 | } 46 | }() 47 | return adjAngle 48 | } 49 | 50 | override func viewDidLoad() { 51 | super.viewDidLoad() 52 | locationManager.delegate = locationDelegate 53 | 54 | locationDelegate.locationCallback = { location in 55 | self.latestLocation = location 56 | } 57 | 58 | locationDelegate.headingCallback = { newHeading in 59 | 60 | func computeNewAngle(with newAngle: CGFloat) -> CGFloat { 61 | let heading: CGFloat = { 62 | let originalHeading = self.yourLocationBearing - newAngle.degreesToRadians 63 | switch UIDevice.current.orientation { 64 | case .faceDown: return -originalHeading 65 | default: return originalHeading 66 | } 67 | }() 68 | 69 | return CGFloat(self.orientationAdjustment().degreesToRadians + heading) 70 | } 71 | 72 | UIView.animate(withDuration: 0.5) { 73 | let angle = computeNewAngle(with: CGFloat(newHeading)) 74 | self.imageView.transform = CGAffineTransform(rotationAngle: angle) 75 | } 76 | } 77 | 78 | let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(CompassViewController.showMap)) 79 | view.addGestureRecognizer(tapGestureRecognizer) 80 | } 81 | 82 | func showMap() { 83 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 84 | let mapViewController = storyboard.instantiateViewController(withIdentifier: "MapViewController") 85 | ((mapViewController as? UINavigationController)?.viewControllers.first as? MapViewController)?.delegate = self 86 | self.present(mapViewController, animated: true, completion: nil) 87 | } 88 | } 89 | 90 | extension CompassViewController: MapViewControllerDelegate { 91 | func update(location: CLLocation) { 92 | yourLocation = location 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /compass/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Compass ∙ 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | Compass ∙ 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 2 23 | LSRequiresIPhoneOS 24 | 25 | NSLocationWhenInUseUsageDescription 26 | The device location is used to compare it with your destinations. 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | magnetometer 35 | gps 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeRight 41 | UIInterfaceOrientationLandscapeLeft 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /compass/LocationDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocationDelegate.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 05/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | 12 | class LocationDelegate: NSObject, CLLocationManagerDelegate { 13 | var locationCallback: ((CLLocation) -> ())? = nil 14 | var headingCallback: ((CLLocationDirection) -> ())? = nil 15 | 16 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 17 | guard let currentLocation = locations.last else { return } 18 | locationCallback?(currentLocation) 19 | } 20 | 21 | func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) { 22 | headingCallback?(newHeading.trueHeading) 23 | } 24 | 25 | func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { 26 | print("⚠️ Error while updating location " + error.localizedDescription) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compass/MapViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapViewController.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 23/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import MapKit 11 | 12 | class MapViewController: UIViewController { 13 | var delegate: MapViewControllerDelegate! 14 | @IBOutlet weak var mapView: MKMapView! 15 | 16 | @IBAction func cancelTap(_ sender: UIBarButtonItem) { 17 | self.dismiss(animated: true, completion: nil) 18 | } 19 | 20 | @IBAction func resetTap(_ sender: UIBarButtonItem) { 21 | delegate.update(location: CLLocation(latitude: 90, longitude: 0)) 22 | self.dismiss(animated: true, completion: nil) 23 | } 24 | 25 | override func viewWillAppear(_ animated: Bool) { 26 | mapView.showsUserLocation = true 27 | if #available(iOS 9, *) { 28 | mapView.showsScale = true 29 | mapView.showsCompass = true 30 | } 31 | } 32 | 33 | override func viewDidAppear(_ animated: Bool) { 34 | super.viewDidAppear(animated) 35 | let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MapViewController.didTap(_:))) 36 | mapView.addGestureRecognizer(gestureRecognizer) 37 | } 38 | 39 | public func didTap(_ gestureRecognizer: UIGestureRecognizer) { 40 | let location = gestureRecognizer.location(in: mapView) 41 | let coordinate = mapView.convert(location, toCoordinateFrom: mapView) 42 | 43 | delegate.update(location: CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) 44 | self.dismiss(animated: true, completion: nil) 45 | } 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /compass/MapViewControllerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapViewControllerDelegate.swift 3 | // compass 4 | // 5 | // Created by Federico Zanetello on 23/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | 12 | protocol MapViewControllerDelegate { 13 | func update(location: CLLocation) 14 | } 15 | -------------------------------------------------------------------------------- /compass/UserDefauts+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefauts+Extensions.swift 3 | // Compass 4 | // 5 | // Created by Federico Zanetello on 28/04/2017. 6 | // Copyright © 2017 Kimchi Media. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import CoreLocation 11 | 12 | extension UserDefaults { 13 | var currentLocation: CLLocation { 14 | get { return CLLocation(latitude: latitude ?? 90, longitude: longitude ?? 0) } // default value is North Pole (lat: 90, long: 0) 15 | set { latitude = newValue.coordinate.latitude 16 | longitude = newValue.coordinate.longitude } 17 | } 18 | 19 | private var latitude: Double? { 20 | get { 21 | if let _ = object(forKey: #function) { 22 | return double(forKey: #function) 23 | } 24 | return nil 25 | } 26 | set { set(newValue, forKey: #function) } 27 | } 28 | 29 | private var longitude: Double? { 30 | get { 31 | if let _ = object(forKey: #function) { 32 | return double(forKey: #function) 33 | } 34 | return nil 35 | } 36 | set { set(newValue, forKey: #function) } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zntfdr/Compass/14c69b3dda5d36e568f4e6ffff97bd2a0c2b3455/logo.png --------------------------------------------------------------------------------