├── .gitignore ├── PSLocationManager.podspec ├── PSLocationManager.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── isenhower.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── isenhower.xcuserdatad │ └── xcschemes │ ├── PSLocationManager.xcscheme │ └── xcschememanagement.plist ├── PSLocationManager ├── AppDelegate.h ├── AppDelegate.m ├── PSLocationManager-Info.plist ├── PSLocationManager-Prefix.pch ├── PSLocationManager.h ├── PSLocationManager.m ├── ViewController.h ├── ViewController.m ├── en.lproj │ ├── InfoPlist.strings │ ├── ViewController_iPad.xib │ └── ViewController_iPhone.xib └── main.m └── README /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /PSLocationManager.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "PSLocationManager" 4 | s.version = "1.0.0" 5 | s.summary = "An Objective C class to track a user's distance and speed via GPS on iOS, using CoreLocation." 6 | s.description = <<-DESC 7 | An Objective C class to track a user's distance and speed via GPS on iOS, using CoreLocation 8 | DESC 9 | 10 | s.homepage = "https://github.com/perspecdev/PSLocationManager" 11 | s.license = 'MIT' 12 | s.author = { "Daniel Isenhower" => "daniel@perspecdev.com" } 13 | 14 | s.platform = :ios, '6.0' 15 | s.source = { :git => "https://github.com/perspecdev/PSLocationManager.git", :tag => "1.0.0" } 16 | s.source_files = 'PSLocationManager/PSLocationManager.{h,m}' 17 | 18 | s.framework = 'CoreLocation' 19 | s.requires_arc = true 20 | end 21 | -------------------------------------------------------------------------------- /PSLocationManager.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 04EFB2D014F4A89300715B64 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EFB2CF14F4A89300715B64 /* UIKit.framework */; }; 11 | 04EFB2D214F4A89300715B64 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EFB2D114F4A89300715B64 /* Foundation.framework */; }; 12 | 04EFB2D414F4A89300715B64 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04EFB2D314F4A89300715B64 /* CoreGraphics.framework */; }; 13 | 04EFB2DA14F4A89300715B64 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 04EFB2D814F4A89300715B64 /* InfoPlist.strings */; }; 14 | 04EFB2DC14F4A89300715B64 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 04EFB2DB14F4A89300715B64 /* main.m */; }; 15 | 04EFB2E014F4A89300715B64 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 04EFB2DF14F4A89300715B64 /* AppDelegate.m */; }; 16 | 04EFB2E314F4A89300715B64 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 04EFB2E214F4A89300715B64 /* ViewController.m */; }; 17 | 04EFB2E614F4A89300715B64 /* ViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04EFB2E414F4A89300715B64 /* ViewController_iPhone.xib */; }; 18 | 04EFB2E914F4A89300715B64 /* ViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04EFB2E714F4A89300715B64 /* ViewController_iPad.xib */; }; 19 | 04EFB2F314F4AFBD00715B64 /* PSLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04EFB2F014F4A8C300715B64 /* PSLocationManager.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 04EFB2CB14F4A89300715B64 /* PSLocationManager.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PSLocationManager.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 04EFB2CF14F4A89300715B64 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 25 | 04EFB2D114F4A89300715B64 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 26 | 04EFB2D314F4A89300715B64 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 27 | 04EFB2D714F4A89300715B64 /* PSLocationManager-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "PSLocationManager-Info.plist"; sourceTree = ""; }; 28 | 04EFB2D914F4A89300715B64 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 29 | 04EFB2DB14F4A89300715B64 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | 04EFB2DD14F4A89300715B64 /* PSLocationManager-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PSLocationManager-Prefix.pch"; sourceTree = ""; }; 31 | 04EFB2DE14F4A89300715B64 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 32 | 04EFB2DF14F4A89300715B64 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 33 | 04EFB2E114F4A89300715B64 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 34 | 04EFB2E214F4A89300715B64 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 35 | 04EFB2E514F4A89300715B64 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPhone.xib; sourceTree = ""; }; 36 | 04EFB2E814F4A89300715B64 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController_iPad.xib; sourceTree = ""; }; 37 | 04EFB2EF14F4A8C300715B64 /* PSLocationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PSLocationManager.h; sourceTree = ""; }; 38 | 04EFB2F014F4A8C300715B64 /* PSLocationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PSLocationManager.m; sourceTree = ""; }; 39 | 04EFB2F114F4A99700715B64 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | 04EFB2C814F4A89300715B64 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | 04EFB2D014F4A89300715B64 /* UIKit.framework in Frameworks */, 48 | 04EFB2D214F4A89300715B64 /* Foundation.framework in Frameworks */, 49 | 04EFB2D414F4A89300715B64 /* CoreGraphics.framework in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 04EFB2C014F4A89200715B64 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 04EFB2D514F4A89300715B64 /* PSLocationManager */, 60 | 04EFB2CE14F4A89300715B64 /* Frameworks */, 61 | 04EFB2CC14F4A89300715B64 /* Products */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | 04EFB2CC14F4A89300715B64 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 04EFB2CB14F4A89300715B64 /* PSLocationManager.app */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 04EFB2CE14F4A89300715B64 /* Frameworks */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 04EFB2F114F4A99700715B64 /* CoreLocation.framework */, 77 | 04EFB2CF14F4A89300715B64 /* UIKit.framework */, 78 | 04EFB2D114F4A89300715B64 /* Foundation.framework */, 79 | 04EFB2D314F4A89300715B64 /* CoreGraphics.framework */, 80 | ); 81 | name = Frameworks; 82 | sourceTree = ""; 83 | }; 84 | 04EFB2D514F4A89300715B64 /* PSLocationManager */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 04EFB2DE14F4A89300715B64 /* AppDelegate.h */, 88 | 04EFB2DF14F4A89300715B64 /* AppDelegate.m */, 89 | 04EFB2EF14F4A8C300715B64 /* PSLocationManager.h */, 90 | 04EFB2F014F4A8C300715B64 /* PSLocationManager.m */, 91 | 04EFB2D614F4A89300715B64 /* Supporting Files */, 92 | 04EFB2E114F4A89300715B64 /* ViewController.h */, 93 | 04EFB2E214F4A89300715B64 /* ViewController.m */, 94 | 04EFB2E714F4A89300715B64 /* ViewController_iPad.xib */, 95 | 04EFB2E414F4A89300715B64 /* ViewController_iPhone.xib */, 96 | ); 97 | path = PSLocationManager; 98 | sourceTree = ""; 99 | }; 100 | 04EFB2D614F4A89300715B64 /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 04EFB2D714F4A89300715B64 /* PSLocationManager-Info.plist */, 104 | 04EFB2D814F4A89300715B64 /* InfoPlist.strings */, 105 | 04EFB2DB14F4A89300715B64 /* main.m */, 106 | 04EFB2DD14F4A89300715B64 /* PSLocationManager-Prefix.pch */, 107 | ); 108 | name = "Supporting Files"; 109 | sourceTree = ""; 110 | }; 111 | /* End PBXGroup section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | 04EFB2CA14F4A89300715B64 /* PSLocationManager */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 04EFB2EC14F4A89300715B64 /* Build configuration list for PBXNativeTarget "PSLocationManager" */; 117 | buildPhases = ( 118 | 04EFB2C714F4A89300715B64 /* Sources */, 119 | 04EFB2C814F4A89300715B64 /* Frameworks */, 120 | 04EFB2C914F4A89300715B64 /* Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = PSLocationManager; 127 | productName = PSLocationManager; 128 | productReference = 04EFB2CB14F4A89300715B64 /* PSLocationManager.app */; 129 | productType = "com.apple.product-type.application"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | 04EFB2C214F4A89200715B64 /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastUpgradeCheck = 0430; 138 | }; 139 | buildConfigurationList = 04EFB2C514F4A89200715B64 /* Build configuration list for PBXProject "PSLocationManager" */; 140 | compatibilityVersion = "Xcode 3.2"; 141 | developmentRegion = English; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | ); 146 | mainGroup = 04EFB2C014F4A89200715B64; 147 | productRefGroup = 04EFB2CC14F4A89300715B64 /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 04EFB2CA14F4A89300715B64 /* PSLocationManager */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 04EFB2C914F4A89300715B64 /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 04EFB2DA14F4A89300715B64 /* InfoPlist.strings in Resources */, 162 | 04EFB2E614F4A89300715B64 /* ViewController_iPhone.xib in Resources */, 163 | 04EFB2E914F4A89300715B64 /* ViewController_iPad.xib in Resources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXSourcesBuildPhase section */ 170 | 04EFB2C714F4A89300715B64 /* Sources */ = { 171 | isa = PBXSourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 04EFB2DC14F4A89300715B64 /* main.m in Sources */, 175 | 04EFB2E014F4A89300715B64 /* AppDelegate.m in Sources */, 176 | 04EFB2E314F4A89300715B64 /* ViewController.m in Sources */, 177 | 04EFB2F314F4AFBD00715B64 /* PSLocationManager.m in Sources */, 178 | ); 179 | runOnlyForDeploymentPostprocessing = 0; 180 | }; 181 | /* End PBXSourcesBuildPhase section */ 182 | 183 | /* Begin PBXVariantGroup section */ 184 | 04EFB2D814F4A89300715B64 /* InfoPlist.strings */ = { 185 | isa = PBXVariantGroup; 186 | children = ( 187 | 04EFB2D914F4A89300715B64 /* en */, 188 | ); 189 | name = InfoPlist.strings; 190 | sourceTree = ""; 191 | }; 192 | 04EFB2E414F4A89300715B64 /* ViewController_iPhone.xib */ = { 193 | isa = PBXVariantGroup; 194 | children = ( 195 | 04EFB2E514F4A89300715B64 /* en */, 196 | ); 197 | name = ViewController_iPhone.xib; 198 | sourceTree = ""; 199 | }; 200 | 04EFB2E714F4A89300715B64 /* ViewController_iPad.xib */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 04EFB2E814F4A89300715B64 /* en */, 204 | ); 205 | name = ViewController_iPad.xib; 206 | sourceTree = ""; 207 | }; 208 | /* End PBXVariantGroup section */ 209 | 210 | /* Begin XCBuildConfiguration section */ 211 | 04EFB2EA14F4A89300715B64 /* Debug */ = { 212 | isa = XCBuildConfiguration; 213 | buildSettings = { 214 | ALWAYS_SEARCH_USER_PATHS = NO; 215 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 216 | CLANG_ENABLE_OBJC_ARC = YES; 217 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 218 | COPY_PHASE_STRIP = NO; 219 | GCC_C_LANGUAGE_STANDARD = gnu99; 220 | GCC_DYNAMIC_NO_PIC = NO; 221 | GCC_OPTIMIZATION_LEVEL = 0; 222 | GCC_PREPROCESSOR_DEFINITIONS = ( 223 | "DEBUG=1", 224 | "$(inherited)", 225 | ); 226 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 227 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 232 | SDKROOT = iphoneos; 233 | TARGETED_DEVICE_FAMILY = "1,2"; 234 | }; 235 | name = Debug; 236 | }; 237 | 04EFB2EB14F4A89300715B64 /* Release */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 244 | COPY_PHASE_STRIP = YES; 245 | GCC_C_LANGUAGE_STANDARD = gnu99; 246 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 248 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 249 | GCC_WARN_UNUSED_VARIABLE = YES; 250 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 251 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 252 | SDKROOT = iphoneos; 253 | TARGETED_DEVICE_FAMILY = "1,2"; 254 | VALIDATE_PRODUCT = YES; 255 | }; 256 | name = Release; 257 | }; 258 | 04EFB2ED14F4A89300715B64 /* Debug */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 262 | GCC_PREFIX_HEADER = "PSLocationManager/PSLocationManager-Prefix.pch"; 263 | INFOPLIST_FILE = "PSLocationManager/PSLocationManager-Info.plist"; 264 | PRODUCT_NAME = "$(TARGET_NAME)"; 265 | WRAPPER_EXTENSION = app; 266 | }; 267 | name = Debug; 268 | }; 269 | 04EFB2EE14F4A89300715B64 /* Release */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 273 | GCC_PREFIX_HEADER = "PSLocationManager/PSLocationManager-Prefix.pch"; 274 | INFOPLIST_FILE = "PSLocationManager/PSLocationManager-Info.plist"; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | WRAPPER_EXTENSION = app; 277 | }; 278 | name = Release; 279 | }; 280 | /* End XCBuildConfiguration section */ 281 | 282 | /* Begin XCConfigurationList section */ 283 | 04EFB2C514F4A89200715B64 /* Build configuration list for PBXProject "PSLocationManager" */ = { 284 | isa = XCConfigurationList; 285 | buildConfigurations = ( 286 | 04EFB2EA14F4A89300715B64 /* Debug */, 287 | 04EFB2EB14F4A89300715B64 /* Release */, 288 | ); 289 | defaultConfigurationIsVisible = 0; 290 | defaultConfigurationName = Release; 291 | }; 292 | 04EFB2EC14F4A89300715B64 /* Build configuration list for PBXNativeTarget "PSLocationManager" */ = { 293 | isa = XCConfigurationList; 294 | buildConfigurations = ( 295 | 04EFB2ED14F4A89300715B64 /* Debug */, 296 | 04EFB2EE14F4A89300715B64 /* Release */, 297 | ); 298 | defaultConfigurationIsVisible = 0; 299 | defaultConfigurationName = Release; 300 | }; 301 | /* End XCConfigurationList section */ 302 | }; 303 | rootObject = 04EFB2C214F4A89200715B64 /* Project object */; 304 | } 305 | -------------------------------------------------------------------------------- /PSLocationManager.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PSLocationManager.xcodeproj/project.xcworkspace/xcuserdata/isenhower.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/perspecdev/PSLocationManager/21c92bcd0dd1cf78efc16d9d49ce4ebe3d55537c/PSLocationManager.xcodeproj/project.xcworkspace/xcuserdata/isenhower.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PSLocationManager.xcodeproj/xcuserdata/isenhower.xcuserdatad/xcschemes/PSLocationManager.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /PSLocationManager.xcodeproj/xcuserdata/isenhower.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PSLocationManager.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 04EFB2CA14F4A89300715B64 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PSLocationManager/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PSLocationManager 4 | // 5 | // Created by Daniel Isenhower on 2/22/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /PSLocationManager/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PSLocationManager 4 | // 5 | // Created by Daniel Isenhower on 2/22/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | #import "ViewController.h" 12 | 13 | @implementation AppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize viewController = _viewController; 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | // Override point for customization after application launch. 22 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 23 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil]; 24 | } else { 25 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil]; 26 | } 27 | self.window.rootViewController = self.viewController; 28 | [self.window makeKeyAndVisible]; 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application 33 | { 34 | // 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. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application 39 | { 40 | // 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. 41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | } 43 | 44 | - (void)applicationWillEnterForeground:(UIApplication *)application 45 | { 46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 47 | } 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application 50 | { 51 | // 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. 52 | } 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application 55 | { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /PSLocationManager/PSLocationManager-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.perspecdev.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /PSLocationManager/PSLocationManager-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PSLocationManager' target in the 'PSLocationManager' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /PSLocationManager/PSLocationManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // LocationManager.h 3 | // Faster 4 | // 5 | // Created by Daniel Isenhower on 1/6/12. 6 | // daniel@perspecdev.com 7 | // Copyright (c) 2012 PerspecDev Solutions LLC. All rights reserved. 8 | // 9 | // For more details, check out the blog post about this here: 10 | // http://perspecdev.com/blog/2012/02/22/using-corelocation-on-ios-to-track-a-users-distance-and-speed/ 11 | // 12 | // Want to use this code in your app? Feel free! I would love it if you would send me a quick email 13 | // about your project. 14 | // 15 | // 16 | // 17 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 18 | // associated documentation files (the "Software"), to deal in the Software without restriction, 19 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, 20 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 21 | // furnished to do so, subject to the following conditions: 22 | // 23 | // The above copyright notice and this permission notice shall be included in all copies or 24 | // substantial portions of the Software. 25 | // 26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 27 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 29 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | 32 | #import 33 | #import 34 | 35 | @class PSLocationManager; 36 | 37 | typedef enum { 38 | PSLocationManagerGPSSignalStrengthInvalid = 0 39 | , PSLocationManagerGPSSignalStrengthWeak 40 | , PSLocationManagerGPSSignalStrengthStrong 41 | } PSLocationManagerGPSSignalStrength; 42 | 43 | @protocol PSLocationManagerDelegate 44 | 45 | @optional 46 | - (void)locationManager:(PSLocationManager *)locationManager signalStrengthChanged:(PSLocationManagerGPSSignalStrength)signalStrength; 47 | - (void)locationManagerSignalConsistentlyWeak:(PSLocationManager *)locationManager; 48 | - (void)locationManager:(PSLocationManager *)locationManager distanceUpdated:(CLLocationDistance)distance; 49 | - (void)locationManager:(PSLocationManager *)locationManager waypoint:(CLLocation *)waypoint calculatedSpeed:(double)calculatedSpeed; 50 | - (void)locationManager:(PSLocationManager *)locationManager error:(NSError *)error; 51 | - (void)locationManager:(PSLocationManager *)locationManager debugText:(NSString *)text; 52 | 53 | @end 54 | 55 | @interface PSLocationManager : NSObject 56 | 57 | @property (nonatomic, weak) id delegate; 58 | @property (nonatomic, readonly) PSLocationManagerGPSSignalStrength signalStrength; 59 | @property (nonatomic, readonly) CLLocationDistance totalDistance; 60 | @property (nonatomic, readonly) NSTimeInterval totalSeconds; 61 | @property (nonatomic, readonly) double currentSpeed; 62 | 63 | + (PSLocationManager *)sharedLocationManager; 64 | 65 | - (BOOL)prepLocationUpdates; // this must be called before startLocationUpdates (best to call it early so we can get an early lock on location) 66 | - (BOOL)startLocationUpdates; 67 | - (void)stopLocationUpdates; 68 | - (void)resetLocationUpdates; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /PSLocationManager/PSLocationManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // LocationManager.m 3 | // Faster 4 | // 5 | // Created by Daniel Isenhower on 1/6/12. 6 | // daniel@perspecdev.com 7 | // Copyright (c) 2012 PerspecDev Solutions LLC. All rights reserved. 8 | // 9 | // For more details, check out the blog post about this here: 10 | // http://perspecdev.com/blog/2012/02/22/using-corelocation-on-ios-to-track-a-users-distance-and-speed/ 11 | // 12 | // Want to use this code in your app? Feel free! I would love it if you would send me a quick email 13 | // about your project. 14 | // 15 | // 16 | // 17 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 18 | // associated documentation files (the "Software"), to deal in the Software without restriction, 19 | // including without limitation the rights to use, copy, modify, merge, publish, distribute, 20 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 21 | // furnished to do so, subject to the following conditions: 22 | // 23 | // The above copyright notice and this permission notice shall be included in all copies or 24 | // substantial portions of the Software. 25 | // 26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 27 | // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 29 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | 32 | static const NSUInteger kDistanceFilter = 5; // the minimum distance (meters) for which we want to receive location updates (see docs for CLLocationManager.distanceFilter) 33 | static const NSUInteger kHeadingFilter = 30; // the minimum angular change (degrees) for which we want to receive heading updates (see docs for CLLocationManager.headingFilter) 34 | static const NSUInteger kDistanceAndSpeedCalculationInterval = 3; // the interval (seconds) at which we calculate the user's distance and speed 35 | static const NSUInteger kMinimumLocationUpdateInterval = 10; // the interval (seconds) at which we ping for a new location if we haven't received one yet 36 | static const NSUInteger kNumLocationHistoriesToKeep = 5; // the number of locations to store in history so that we can look back at them and determine which is most accurate 37 | static const NSUInteger kValidLocationHistoryDeltaInterval = 3; // the maximum valid age in seconds of a location stored in the location history 38 | static const NSUInteger kNumSpeedHistoriesToAverage = 3; // the number of speeds to store in history so that we can average them to get the current speed 39 | static const NSUInteger kPrioritizeFasterSpeeds = 1; // if > 0, the currentSpeed and complete speed history will automatically be set to to the new speed if the new speed is faster than the averaged speed 40 | static const NSUInteger kMinLocationsNeededToUpdateDistanceAndSpeed = 3; // the number of locations needed in history before we will even update the current distance and speed 41 | static const CGFloat kRequiredHorizontalAccuracy = 20.0; // the required accuracy in meters for a location. if we receive anything above this number, the delegate will be informed that the signal is weak 42 | static const CGFloat kMaximumAcceptableHorizontalAccuracy = 70.0; // the maximum acceptable accuracy in meters for a location. anything above this number will be completely ignored 43 | static const NSUInteger kGPSRefinementInterval = 15; // the number of seconds at which we will attempt to achieve kRequiredHorizontalAccuracy before giving up and accepting kMaximumAcceptableHorizontalAccuracy 44 | 45 | static const CGFloat kSpeedNotSet = -1.0; 46 | 47 | #import "PSLocationManager.h" 48 | 49 | @interface PSLocationManager () 50 | 51 | @property (nonatomic, strong) CLLocationManager *locationManager; 52 | @property (nonatomic, strong) NSTimer *locationPingTimer; 53 | @property (nonatomic) PSLocationManagerGPSSignalStrength signalStrength; 54 | @property (nonatomic, strong) CLLocation *lastRecordedLocation; 55 | @property (nonatomic) CLLocationDistance totalDistance; 56 | @property (nonatomic, strong) NSMutableArray *locationHistory; 57 | @property (nonatomic, strong) NSDate *startTimestamp; 58 | @property (nonatomic) double currentSpeed; 59 | @property (nonatomic, strong) NSMutableArray *speedHistory; 60 | @property (nonatomic) NSUInteger lastDistanceAndSpeedCalculation; 61 | @property (nonatomic) BOOL forceDistanceAndSpeedCalculation; 62 | @property (nonatomic) NSTimeInterval pauseDelta; 63 | @property (nonatomic) NSTimeInterval pauseDeltaStart; 64 | @property (nonatomic) BOOL readyToExposeDistanceAndSpeed; 65 | @property (nonatomic) BOOL checkingSignalStrength; 66 | @property (nonatomic) BOOL allowMaximumAcceptableAccuracy; 67 | 68 | - (void)checkSustainedSignalStrength; 69 | - (void)requestNewLocation; 70 | 71 | @end 72 | 73 | 74 | @implementation PSLocationManager 75 | 76 | @synthesize delegate = _delegate; 77 | 78 | @synthesize locationManager = _locationManager; 79 | @synthesize locationPingTimer = _locationPingTimer; 80 | @synthesize signalStrength = _signalStrength; 81 | @synthesize lastRecordedLocation = _lastRecordedLocation; 82 | @synthesize totalDistance = _totalDistance; 83 | @synthesize locationHistory = _locationHistory; 84 | @synthesize totalSeconds = _totalSeconds; 85 | @synthesize startTimestamp = _startTimestamp; 86 | @synthesize currentSpeed = _currentSpeed; 87 | @synthesize speedHistory = _speedHistory; 88 | @synthesize lastDistanceAndSpeedCalculation = _lastDistanceAndSpeedCalculation; 89 | @synthesize forceDistanceAndSpeedCalculation = _forceDistanceAndSpeedCalculation; 90 | @synthesize pauseDelta = _pauseDelta; 91 | @synthesize pauseDeltaStart = _pauseDeltaStart; 92 | @synthesize readyToExposeDistanceAndSpeed = _readyToExposeDistanceAndSpeed; 93 | @synthesize allowMaximumAcceptableAccuracy = _allowMaximumAcceptableAccuracy; 94 | @synthesize checkingSignalStrength = _checkingSignalStrength; 95 | 96 | + (id)sharedLocationManager { 97 | static dispatch_once_t pred; 98 | static PSLocationManager *locationManagerSingleton = nil; 99 | 100 | dispatch_once(&pred, ^{ 101 | locationManagerSingleton = [[self alloc] init]; 102 | }); 103 | return locationManagerSingleton; 104 | } 105 | 106 | - (id)init { 107 | if ((self = [super init])) { 108 | if ([CLLocationManager locationServicesEnabled]) { 109 | self.locationManager = [[CLLocationManager alloc] init]; 110 | self.locationManager.delegate = self; 111 | self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; 112 | self.locationManager.distanceFilter = kDistanceFilter; 113 | self.locationManager.headingFilter = kHeadingFilter; 114 | } 115 | 116 | self.locationHistory = [NSMutableArray arrayWithCapacity:kNumLocationHistoriesToKeep]; 117 | self.speedHistory = [NSMutableArray arrayWithCapacity:kNumSpeedHistoriesToAverage]; 118 | [self resetLocationUpdates]; 119 | } 120 | 121 | return self; 122 | } 123 | 124 | - (void)dealloc { 125 | [self.locationManager stopUpdatingLocation]; 126 | [self.locationManager stopUpdatingHeading]; 127 | self.locationManager.delegate = nil; 128 | self.locationManager = nil; 129 | 130 | self.lastRecordedLocation = nil; 131 | self.locationHistory = nil; 132 | self.speedHistory = nil; 133 | } 134 | 135 | - (void)setSignalStrength:(PSLocationManagerGPSSignalStrength)signalStrength { 136 | BOOL needToUpdateDelegate = NO; 137 | if (_signalStrength != signalStrength) { 138 | needToUpdateDelegate = YES; 139 | } 140 | 141 | _signalStrength = signalStrength; 142 | 143 | if (self.signalStrength == PSLocationManagerGPSSignalStrengthStrong) { 144 | self.allowMaximumAcceptableAccuracy = NO; 145 | } else if (self.signalStrength == PSLocationManagerGPSSignalStrengthWeak) { 146 | [self checkSustainedSignalStrength]; 147 | } 148 | 149 | if (needToUpdateDelegate) { 150 | if ([self.delegate respondsToSelector:@selector(locationManager:signalStrengthChanged:)]) { 151 | [self.delegate locationManager:self signalStrengthChanged:self.signalStrength]; 152 | } 153 | } 154 | } 155 | 156 | - (void)setTotalDistance:(CLLocationDistance)totalDistance { 157 | _totalDistance = totalDistance; 158 | 159 | if (self.currentSpeed != kSpeedNotSet) { 160 | if ([self.delegate respondsToSelector:@selector(locationManager:distanceUpdated:)]) { 161 | [self.delegate locationManager:self distanceUpdated:self.totalDistance]; 162 | } 163 | } 164 | } 165 | 166 | - (NSTimeInterval)totalSeconds { 167 | return ([self.startTimestamp timeIntervalSinceNow] * -1) - self.pauseDelta; 168 | } 169 | 170 | - (void)checkSustainedSignalStrength { 171 | if (!self.checkingSignalStrength) { 172 | self.checkingSignalStrength = YES; 173 | 174 | double delayInSeconds = kGPSRefinementInterval; 175 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 176 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 177 | self.checkingSignalStrength = NO; 178 | if (self.signalStrength == PSLocationManagerGPSSignalStrengthWeak) { 179 | self.allowMaximumAcceptableAccuracy = YES; 180 | if ([self.delegate respondsToSelector:@selector(locationManagerSignalConsistentlyWeak:)]) { 181 | [self.delegate locationManagerSignalConsistentlyWeak:self]; 182 | } 183 | } else if (self.signalStrength == PSLocationManagerGPSSignalStrengthInvalid) { 184 | self.allowMaximumAcceptableAccuracy = YES; 185 | self.signalStrength = PSLocationManagerGPSSignalStrengthWeak; 186 | if ([self.delegate respondsToSelector:@selector(locationManagerSignalConsistentlyWeak:)]) { 187 | [self.delegate locationManagerSignalConsistentlyWeak:self]; 188 | } 189 | } 190 | }); 191 | } 192 | } 193 | 194 | - (void)requestNewLocation { 195 | [self.locationManager stopUpdatingLocation]; 196 | [self.locationManager startUpdatingLocation]; 197 | } 198 | 199 | - (BOOL)prepLocationUpdates { 200 | if ([CLLocationManager locationServicesEnabled]) { 201 | [self.locationHistory removeAllObjects]; 202 | [self.speedHistory removeAllObjects]; 203 | self.lastDistanceAndSpeedCalculation = 0; 204 | self.currentSpeed = kSpeedNotSet; 205 | self.readyToExposeDistanceAndSpeed = NO; 206 | self.signalStrength = PSLocationManagerGPSSignalStrengthInvalid; 207 | self.allowMaximumAcceptableAccuracy = NO; 208 | 209 | self.forceDistanceAndSpeedCalculation = YES; 210 | [self.locationManager startUpdatingLocation]; 211 | [self.locationManager startUpdatingHeading]; 212 | 213 | [self checkSustainedSignalStrength]; 214 | 215 | return YES; 216 | } else { 217 | return NO; 218 | } 219 | } 220 | 221 | - (BOOL)startLocationUpdates { 222 | if ([CLLocationManager locationServicesEnabled]) { 223 | self.readyToExposeDistanceAndSpeed = YES; 224 | 225 | [self.locationManager startUpdatingLocation]; 226 | [self.locationManager startUpdatingHeading]; 227 | 228 | if (self.pauseDeltaStart > 0) { 229 | self.pauseDelta += ([NSDate timeIntervalSinceReferenceDate] - self.pauseDeltaStart); 230 | self.pauseDeltaStart = 0; 231 | } 232 | 233 | return YES; 234 | } else { 235 | return NO; 236 | } 237 | } 238 | 239 | - (void)stopLocationUpdates { 240 | [self.locationPingTimer invalidate]; 241 | [self.locationManager stopUpdatingLocation]; 242 | [self.locationManager stopUpdatingHeading]; 243 | self.pauseDeltaStart = [NSDate timeIntervalSinceReferenceDate]; 244 | self.lastRecordedLocation = nil; 245 | } 246 | 247 | - (void)resetLocationUpdates { 248 | self.totalDistance = 0; 249 | self.startTimestamp = [NSDate dateWithTimeIntervalSinceNow:0]; 250 | self.forceDistanceAndSpeedCalculation = NO; 251 | self.pauseDelta = 0; 252 | self.pauseDeltaStart = 0; 253 | } 254 | 255 | #pragma mark CLLocationManagerDelegate 256 | 257 | - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 258 | // since the oldLocation might be from some previous use of core location, we need to make sure we're getting data from this run 259 | if (oldLocation == nil) return; 260 | BOOL isStaleLocation = ([oldLocation.timestamp compare:self.startTimestamp] == NSOrderedAscending); 261 | 262 | [self.locationPingTimer invalidate]; 263 | 264 | if (newLocation.horizontalAccuracy <= kRequiredHorizontalAccuracy) { 265 | self.signalStrength = PSLocationManagerGPSSignalStrengthStrong; 266 | } else { 267 | self.signalStrength = PSLocationManagerGPSSignalStrengthWeak; 268 | } 269 | 270 | double horizontalAccuracy; 271 | if (self.allowMaximumAcceptableAccuracy) { 272 | horizontalAccuracy = kMaximumAcceptableHorizontalAccuracy; 273 | } else { 274 | horizontalAccuracy = kRequiredHorizontalAccuracy; 275 | } 276 | 277 | if (!isStaleLocation && newLocation.horizontalAccuracy >= 0 && newLocation.horizontalAccuracy <= horizontalAccuracy) { 278 | 279 | [self.locationHistory addObject:newLocation]; 280 | if ([self.locationHistory count] > kNumLocationHistoriesToKeep) { 281 | [self.locationHistory removeObjectAtIndex:0]; 282 | } 283 | 284 | BOOL canUpdateDistanceAndSpeed = NO; 285 | if ([self.locationHistory count] >= kMinLocationsNeededToUpdateDistanceAndSpeed) { 286 | canUpdateDistanceAndSpeed = YES && self.readyToExposeDistanceAndSpeed; 287 | } 288 | 289 | if (self.forceDistanceAndSpeedCalculation || [NSDate timeIntervalSinceReferenceDate] - self.lastDistanceAndSpeedCalculation > kDistanceAndSpeedCalculationInterval) { 290 | self.forceDistanceAndSpeedCalculation = NO; 291 | self.lastDistanceAndSpeedCalculation = [NSDate timeIntervalSinceReferenceDate]; 292 | 293 | CLLocation *lastLocation = (self.lastRecordedLocation != nil) ? self.lastRecordedLocation : oldLocation; 294 | 295 | CLLocation *bestLocation = nil; 296 | CGFloat bestAccuracy = kRequiredHorizontalAccuracy; 297 | for (CLLocation *location in self.locationHistory) { 298 | if ([NSDate timeIntervalSinceReferenceDate] - [location.timestamp timeIntervalSinceReferenceDate] <= kValidLocationHistoryDeltaInterval) { 299 | if (location.horizontalAccuracy <= bestAccuracy && location != lastLocation) { 300 | bestAccuracy = location.horizontalAccuracy; 301 | bestLocation = location; 302 | } 303 | } 304 | } 305 | if (bestLocation == nil) bestLocation = newLocation; 306 | 307 | CLLocationDistance distance = [bestLocation distanceFromLocation:lastLocation]; 308 | if (canUpdateDistanceAndSpeed) self.totalDistance += distance; 309 | self.lastRecordedLocation = bestLocation; 310 | 311 | NSTimeInterval timeSinceLastLocation = [bestLocation.timestamp timeIntervalSinceDate:lastLocation.timestamp]; 312 | if (timeSinceLastLocation > 0) { 313 | CGFloat speed = distance / timeSinceLastLocation; 314 | if (speed <= 0 && [self.speedHistory count] == 0) { 315 | // don't add a speed of 0 as the first item, since it just means we're not moving yet 316 | } else { 317 | [self.speedHistory addObject:[NSNumber numberWithDouble:speed]]; 318 | } 319 | if ([self.speedHistory count] > kNumSpeedHistoriesToAverage) { 320 | [self.speedHistory removeObjectAtIndex:0]; 321 | } 322 | if ([self.speedHistory count] > 1) { 323 | double totalSpeed = 0; 324 | for (NSNumber *speedNumber in self.speedHistory) { 325 | totalSpeed += [speedNumber doubleValue]; 326 | } 327 | if (canUpdateDistanceAndSpeed) { 328 | double newSpeed = totalSpeed / (double)[self.speedHistory count]; 329 | if (kPrioritizeFasterSpeeds > 0 && speed > newSpeed) { 330 | newSpeed = speed; 331 | [self.speedHistory removeAllObjects]; 332 | for (int i=0; i 10 | #import "PSLocationManager.h" 11 | 12 | @interface ViewController : UIViewController 13 | 14 | @property (nonatomic, weak) IBOutlet UILabel *strengthLabel; 15 | @property (nonatomic, weak) IBOutlet UILabel *distanceLabel; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /PSLocationManager/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PSLocationManager 4 | // 5 | // Created by Daniel Isenhower on 2/22/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | @synthesize strengthLabel = _strengthLabel; 18 | @synthesize distanceLabel = _distanceLabel; 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view, typically from a nib. 24 | 25 | [PSLocationManager sharedLocationManager].delegate = self; 26 | [[PSLocationManager sharedLocationManager] prepLocationUpdates]; 27 | [[PSLocationManager sharedLocationManager] startLocationUpdates]; 28 | } 29 | 30 | - (void)viewDidUnload 31 | { 32 | [super viewDidUnload]; 33 | // Release any retained subviews of the main view. 34 | } 35 | 36 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 37 | { 38 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 39 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 40 | } else { 41 | return YES; 42 | } 43 | } 44 | 45 | #pragma mark PSLocationManagerDelegate 46 | 47 | - (void)locationManager:(PSLocationManager *)locationManager signalStrengthChanged:(PSLocationManagerGPSSignalStrength)signalStrength { 48 | NSString *strengthText; 49 | if (signalStrength == PSLocationManagerGPSSignalStrengthWeak) { 50 | strengthText = NSLocalizedString(@"Weak", @""); 51 | } else if (signalStrength == PSLocationManagerGPSSignalStrengthStrong) { 52 | strengthText = NSLocalizedString(@"Strong", @""); 53 | } else { 54 | strengthText = NSLocalizedString(@"...", @""); 55 | } 56 | 57 | self.strengthLabel.text = strengthText; 58 | } 59 | 60 | - (void)locationManagerSignalConsistentlyWeak:(PSLocationManager *)locationManager { 61 | self.strengthLabel.text = NSLocalizedString(@"Consistently Weak", @""); 62 | } 63 | 64 | - (void)locationManager:(PSLocationManager *)locationManager distanceUpdated:(CLLocationDistance)distance { 65 | self.distanceLabel.text = [NSString stringWithFormat:@"%.2f %@", distance, NSLocalizedString(@"meters", @"")]; 66 | } 67 | 68 | - (void)locationManager:(PSLocationManager *)locationManager error:(NSError *)error { 69 | // location services is probably not enabled for the app 70 | self.strengthLabel.text = NSLocalizedString(@"Unable to determine location", @""); 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /PSLocationManager/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /PSLocationManager/en.lproj/ViewController_iPad.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11D50b 6 | 2177 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1173 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUILabel 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBIPadFramework 29 | 30 | 31 | IBFirstResponder 32 | IBIPadFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 290 41 | {{71, 20}, {625, 21}} 42 | 43 | 44 | 45 | _NS:9 46 | NO 47 | YES 48 | 7 49 | NO 50 | IBIPadFramework 51 | Signal Strength: 52 | 53 | 1 54 | MCAwIDAAA 55 | 56 | 57 | 0 58 | 10 59 | 1 60 | 61 | 2 62 | 17 63 | 64 | 65 | Helvetica-Bold 66 | 17 67 | 16 68 | 69 | 70 | 71 | 72 | 290 73 | {{71, 40}, {625, 21}} 74 | 75 | 76 | 77 | _NS:9 78 | NO 79 | YES 80 | 7 81 | NO 82 | IBIPadFramework 83 | ... 84 | 85 | 86 | 0 87 | 10 88 | 1 89 | 90 | 1 91 | 17 92 | 93 | 94 | Helvetica 95 | 17 96 | 16 97 | 98 | 99 | 100 | 101 | 290 102 | {{71, 149}, {625, 21}} 103 | 104 | 105 | _NS:9 106 | NO 107 | YES 108 | 7 109 | NO 110 | IBIPadFramework 111 | ... 112 | 113 | 114 | 0 115 | 10 116 | 1 117 | 118 | 119 | 120 | 121 | 122 | 290 123 | {{71, 125}, {625, 21}} 124 | 125 | 126 | 127 | _NS:9 128 | NO 129 | YES 130 | 7 131 | NO 132 | IBIPadFramework 133 | Total Distance: 134 | 135 | 136 | 0 137 | 10 138 | 1 139 | 140 | 141 | 142 | 143 | {{0, 20}, {768, 1004}} 144 | 145 | 146 | 147 | 148 | 3 149 | MQA 150 | 151 | 2 152 | 153 | 154 | 155 | 2 156 | 157 | IBIPadFramework 158 | 159 | 160 | 161 | 162 | 163 | 164 | view 165 | 166 | 167 | 168 | 3 169 | 170 | 171 | 172 | strengthLabel 173 | 174 | 175 | 176 | 8 177 | 178 | 179 | 180 | distanceLabel 181 | 182 | 183 | 184 | 9 185 | 186 | 187 | 188 | 189 | 190 | 0 191 | 192 | 193 | 194 | 195 | 196 | -1 197 | 198 | 199 | File's Owner 200 | 201 | 202 | -2 203 | 204 | 205 | 206 | 207 | 2 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 4 219 | 220 | 221 | 222 | 223 | 5 224 | 225 | 226 | 227 | 228 | 6 229 | 230 | 231 | 232 | 233 | 7 234 | 235 | 236 | 237 | 238 | 239 | 240 | ViewController 241 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 242 | UIResponder 243 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 244 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 245 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 246 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 247 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 248 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 249 | 250 | 251 | 252 | 253 | 254 | 9 255 | 256 | 257 | 258 | 259 | ViewController 260 | UIViewController 261 | 262 | UILabel 263 | UILabel 264 | 265 | 266 | 267 | distanceLabel 268 | UILabel 269 | 270 | 271 | strengthLabel 272 | UILabel 273 | 274 | 275 | 276 | IBProjectSource 277 | ./Classes/ViewController.h 278 | 279 | 280 | 281 | 282 | 0 283 | IBIPadFramework 284 | YES 285 | 3 286 | 1173 287 | 288 | 289 | -------------------------------------------------------------------------------- /PSLocationManager/en.lproj/ViewController_iPhone.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11D50b 6 | 2177 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1173 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUILabel 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 290 41 | {{0, 20}, {320, 21}} 42 | 43 | 44 | 45 | _NS:9 46 | NO 47 | YES 48 | 7 49 | NO 50 | IBCocoaTouchFramework 51 | Signal Strength: 52 | 53 | 1 54 | MCAwIDAAA 55 | 56 | 57 | 0 58 | 10 59 | 1 60 | 61 | 2 62 | 17 63 | 64 | 65 | Helvetica-Bold 66 | 17 67 | 16 68 | 69 | 70 | 71 | 72 | 290 73 | {{0, 40}, {320, 21}} 74 | 75 | 76 | 77 | _NS:9 78 | NO 79 | YES 80 | 7 81 | NO 82 | IBCocoaTouchFramework 83 | ... 84 | 85 | 86 | 0 87 | 10 88 | 1 89 | 90 | 1 91 | 17 92 | 93 | 94 | Helvetica 95 | 17 96 | 16 97 | 98 | 99 | 100 | 101 | 290 102 | {{0, 149}, {320, 21}} 103 | 104 | 105 | _NS:9 106 | NO 107 | YES 108 | 7 109 | NO 110 | IBCocoaTouchFramework 111 | ... 112 | 113 | 114 | 0 115 | 10 116 | 1 117 | 118 | 119 | 120 | 121 | 122 | 290 123 | {{0, 125}, {320, 21}} 124 | 125 | 126 | _NS:9 127 | NO 128 | YES 129 | 7 130 | NO 131 | IBCocoaTouchFramework 132 | Total Distance: 133 | 134 | 135 | 0 136 | 10 137 | 1 138 | 139 | 140 | 141 | 142 | {{0, 20}, {320, 460}} 143 | 144 | 145 | 146 | 3 147 | MC43NQA 148 | 149 | 2 150 | 151 | 152 | NO 153 | 154 | IBCocoaTouchFramework 155 | 156 | 157 | 158 | 159 | 160 | 161 | view 162 | 163 | 164 | 165 | 7 166 | 167 | 168 | 169 | strengthLabel 170 | 171 | 172 | 173 | 20 174 | 175 | 176 | 177 | distanceLabel 178 | 179 | 180 | 181 | 21 182 | 183 | 184 | 185 | 186 | 187 | 0 188 | 189 | 190 | 191 | 192 | 193 | -1 194 | 195 | 196 | File's Owner 197 | 198 | 199 | -2 200 | 201 | 202 | 203 | 204 | 6 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 16 216 | 217 | 218 | 219 | 220 | 17 221 | 222 | 223 | 224 | 225 | 18 226 | 227 | 228 | 229 | 230 | 19 231 | 232 | 233 | 234 | 235 | 236 | 237 | ViewController 238 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 239 | UIResponder 240 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 241 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 242 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 243 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 244 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 245 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 246 | 247 | 248 | 249 | 250 | 251 | 21 252 | 253 | 254 | 255 | 256 | ViewController 257 | UIViewController 258 | 259 | UILabel 260 | UILabel 261 | 262 | 263 | 264 | distanceLabel 265 | UILabel 266 | 267 | 268 | strengthLabel 269 | UILabel 270 | 271 | 272 | 273 | IBProjectSource 274 | ./Classes/ViewController.h 275 | 276 | 277 | 278 | 279 | 0 280 | IBCocoaTouchFramework 281 | YES 282 | 3 283 | 1173 284 | 285 | 286 | -------------------------------------------------------------------------------- /PSLocationManager/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PSLocationManager 4 | // 5 | // Created by Daniel Isenhower on 2/22/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PSLocationManager allows you to track a user's distance and speed. 2 | 3 | Setup with Cocoapods 4 | -------------------- 5 | * Add ```pod ‚PS’LocationManager``` to your Podfile 6 | * Run ```pod install``` 7 | 8 | Detailed info can be found here: 9 | http://perspecdev.com/blog/2012/02/22/using-corelocation-on-ios-to-track-a-users-distance-and-speed/ 10 | --------------------------------------------------------------------------------