├── .gitattributes ├── .gitignore ├── DDDeviceDetection.h ├── DDDeviceDetection.m ├── LICENSE └── README /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -crlf -diff -merge 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .DS_store 4 | profile 5 | 6 | # XCode 7 | *.mode* 8 | *.perspective* 9 | *.pbxuser* 10 | *tmproj 11 | External/GHUnit/* 12 | PLBlocks.framework/* 13 | *.pyc 14 | 15 | # for Xcode 4 16 | xcuserdata 17 | *.xcworkspace 18 | 19 | # built products 20 | build 21 | *.o 22 | 23 | # Other source repository archive directories 24 | .hg 25 | .svn 26 | CVS 27 | 28 | # Automatic backup files 29 | #~.nib/ 30 | *.swp 31 | *~ 32 | *(Autosaved).rtfd/ 33 | Backup[ ]of[ ]*.pages/ 34 | Backup[ ]of[ ]*.key/ 35 | Backup[ ]of[ ]*.numbers/ 36 | -------------------------------------------------------------------------------- /DDDeviceDetection.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDDeviceDetection.h 3 | // Device Detection 4 | // 5 | // Created by Damien DeVille on 8/17/10. 6 | // Copyright 2010 Damien DeVille. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /* 12 | Feel free to comment the following import if you don't need to test 13 | location capabilities and don't want to import the CoreLocation framework 14 | */ 15 | #import 16 | 17 | /* 18 | Feel free to comment the following import if you don't need to test 19 | audio capabilities and don't want to import the AudioToolbox framework 20 | */ 21 | #import 22 | 23 | /* 24 | Feel free to comment the following import if you don't need to test 25 | message capabilities and don't want to import the MessageUI framework 26 | */ 27 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30000 28 | #import 29 | #endif 30 | 31 | /* 32 | Feel free to comment the following import if you don't need to test 33 | gyroscope capabilities and don't want to import the CoreMotion framework 34 | */ 35 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 36 | #import 37 | #endif 38 | 39 | 40 | @interface DDDeviceDetection : NSObject 41 | 42 | + (NSString *)returnDeviceName ; 43 | + (NSString *)returnOSVersion ; 44 | 45 | // device checking 46 | + (BOOL)isAniPod ; 47 | + (BOOL)isAniPhone ; 48 | + (BOOL)isAniPad ; 49 | + (BOOL)isSimulator ; 50 | 51 | // OS version checking 52 | + (BOOL)isRunningiOS2 ; 53 | + (BOOL)isRunningiOS3 ; 54 | + (BOOL)isRunningiOS4 ; 55 | 56 | // software capabilities checking 57 | + (BOOL)isMultitaskingSupported ; 58 | 59 | // message capabilities 60 | + (BOOL)canSendEmail ; 61 | + (BOOL)canSendSMS ; 62 | 63 | // audio capabilities checking 64 | + (BOOL)isInSilentMode ; 65 | + (BOOL)hasSpeakersOn ; 66 | + (BOOL)hasHeadphonesPlugged ; 67 | 68 | // hardware checking 69 | + (BOOL)hasRetinaDisplay ; 70 | + (BOOL)hasCamera ; 71 | + (BOOL)hasFrontFacingCamera ; 72 | + (BOOL)canRecordVideo ; 73 | + (BOOL)hasRearFlashLight ; 74 | 75 | // needs the CoreLocation framework 76 | + (BOOL)hasCompass ; 77 | 78 | // needs the CoreMotion framework 79 | + (BOOL)hasGyroscope ; 80 | 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /DDDeviceDetection.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDDeviceDetection.m 3 | // Device Detection 4 | // 5 | // Created by Damien DeVille on 8/17/10. 6 | // Copyright 2010 Damien DeVille. All rights reserved. 7 | // 8 | 9 | #import "DDDeviceDetection.h" 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | /* 16 | In case you compile against an earlier version of the SDK 17 | it is safer to (re)define the OS version numbers. 18 | */ 19 | 20 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_0 21 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23 22 | #endif 23 | 24 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_1 25 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26 26 | #endif 27 | 28 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_2 29 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29 30 | #endif 31 | 32 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_0 33 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_0 478.47 34 | #endif 35 | 36 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_1 37 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_1 478.52 38 | #endif 39 | 40 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_2 41 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61 42 | #endif 43 | 44 | #ifndef kCFCoreFoundationVersionNumber_iOS_4_0 45 | #define kCFCoreFoundationVersionNumber_iOS_4_0 550.32 46 | #endif 47 | 48 | #ifndef kCFCoreFoundationVersionNumber_iOS_4_1 49 | #define kCFCoreFoundationVersionNumber_iOS_4_1 550.38 50 | #endif 51 | 52 | #ifndef kCFCoreFoundationVersionNumber_iOS_4_2 53 | #define kCFCoreFoundationVersionNumber_iOS_4_2 550.52 54 | #endif 55 | 56 | /* 57 | the following are only defined in iOS 4.0 so it is worth 58 | defining them in case you do not compile with 4.0 59 | */ 60 | #ifndef UIImagePickerControllerCameraDeviceRear 61 | #define UIImagePickerControllerCameraDeviceRear 0 62 | #endif 63 | 64 | #ifndef UIImagePickerControllerCameraDeviceFront 65 | #define UIImagePickerControllerCameraDeviceFront 1 66 | #endif 67 | 68 | #ifndef kUTTypeMovie 69 | #define kUTTypeMovie @"public.movie" 70 | #endif 71 | 72 | /* 73 | Category on UIScreen defining a scale method matching 74 | the scale property defined in iOS 4.0. 75 | This is mainly to avoid a compiler warning when building 76 | with an earlier version of the SDK 77 | */ 78 | #if __IPHONE_OS_VERSION_MAX_ALLOWED < 40000 79 | @interface UIScreen (ScaleFactor) 80 | - (float)scale ; 81 | @end 82 | @implementation UIScreen (ScaleFactor) 83 | - (float)scale 84 | { 85 | return 1.0f ; 86 | } 87 | @end 88 | #endif 89 | 90 | 91 | @interface DDDeviceDetection (Private) 92 | 93 | + (NSString *)detectPlatform ; 94 | 95 | @end 96 | 97 | 98 | @implementation DDDeviceDetection 99 | 100 | #pragma mark - 101 | #pragma mark Private methods 102 | 103 | + (NSString *)detectPlatform 104 | { 105 | size_t size ; 106 | sysctlbyname("hw.machine", NULL, &size, NULL, 0) ; 107 | char *machine = malloc(size) ; 108 | sysctlbyname("hw.machine", machine, &size, NULL, 0) ; 109 | NSString *platform = [NSString stringWithCString: machine encoding: NSUTF8StringEncoding] ; 110 | free(machine) ; 111 | return platform ; 112 | } 113 | 114 | 115 | 116 | #pragma mark - 117 | #pragma mark Return device name 118 | 119 | + (NSString *)returnDeviceName 120 | { 121 | NSString *platform = [self detectPlatform] ; 122 | if ([platform isEqualToString: @"iPhone1,1"]) 123 | return @"iPhone 1G" ; 124 | if ([platform isEqualToString: @"iPhone1,2"]) 125 | return @"iPhone 3G" ; 126 | if ([platform isEqualToString: @"iPhone2,1"]) 127 | return @"iPhone 3GS" ; 128 | if ([platform isEqualToString: @"iPhone3,1"]) 129 | return @"iPhone 4" ; 130 | if ([platform isEqualToString: @"iPod1,1"]) 131 | return @"iPod Touch 1G" ; 132 | if ([platform isEqualToString: @"iPod2,1"]) 133 | return @"iPod Touch 2G" ; 134 | if ([platform isEqualToString: @"iPod3,1"]) 135 | return @"iPod Touch 3G" ; 136 | if ([platform isEqualToString: @"iPod4,1"]) 137 | return @"iPod Touch 4G" ; 138 | if ([platform isEqualToString: @"iPad1,1"]) 139 | return @"iPad" ; 140 | if ([platform isEqualToString: @"iPad2,1"]) 141 | return @"iPad 2" ; 142 | if ([platform isEqualToString: @"i386"]) 143 | return @"Simulator" ; 144 | return platform ; 145 | } 146 | 147 | + (NSString *)returnOSVersion 148 | { 149 | return [[UIDevice currentDevice] systemVersion] ; 150 | } 151 | 152 | 153 | 154 | #pragma mark - 155 | #pragma mark Detect device type 156 | 157 | + (BOOL)isAniPod 158 | { 159 | NSRange textRange =[[self detectPlatform] rangeOfString: @"iPod"] ; 160 | if(textRange.location != NSNotFound) 161 | return YES ; 162 | return NO ; 163 | } 164 | 165 | + (BOOL)isAniPhone 166 | { 167 | NSRange textRange =[[self detectPlatform] rangeOfString: @"iPhone"] ; 168 | if(textRange.location != NSNotFound) 169 | return YES ; 170 | return NO ; 171 | } 172 | 173 | + (BOOL)isAniPad 174 | { 175 | NSRange textRange =[[self detectPlatform] rangeOfString: @"iPad"] ; 176 | if(textRange.location != NSNotFound) 177 | return YES ; 178 | return NO ; 179 | } 180 | 181 | + (BOOL)isSimulator 182 | { 183 | NSRange textRange =[[self detectPlatform] rangeOfString: @"i386"] ; 184 | if(textRange.location != NSNotFound) 185 | return YES ; 186 | return NO ; 187 | } 188 | 189 | 190 | 191 | #pragma mark - 192 | #pragma mark Detect OS version 193 | 194 | + (BOOL)isRunningiOS2 195 | { 196 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_2_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) 197 | return YES ; 198 | return NO ; 199 | } 200 | 201 | + (BOOL)isRunningiOS3 202 | { 203 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_4_0) 204 | return YES ; 205 | return NO ; 206 | } 207 | 208 | + (BOOL)isRunningiOS4 209 | { 210 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_4_0) 211 | return YES ; 212 | return NO ; 213 | } 214 | 215 | 216 | 217 | #pragma mark - 218 | #pragma mark Detect software capabilities 219 | 220 | + (BOOL)isMultitaskingSupported 221 | { 222 | if ([[UIDevice currentDevice] respondsToSelector: @selector(isMultitaskingSupported)]) 223 | if ([[UIDevice currentDevice] performSelector: @selector(isMultitaskingSupported)]) 224 | return YES ; 225 | return NO ; 226 | } 227 | 228 | 229 | 230 | #pragma mark - 231 | #pragma mark Message capabilities 232 | 233 | + (BOOL)canSendEmail 234 | { 235 | if ([NSClassFromString(@"MFMailComposeViewController") respondsToSelector: @selector(canSendMail)]) 236 | if ([NSClassFromString(@"MFMailComposeViewController") performSelector: @selector(canSendMail)]) 237 | return YES ; 238 | return NO ; 239 | } 240 | 241 | + (BOOL)canSendSMS 242 | { 243 | if ([NSClassFromString(@"MFMessageComposeViewController") respondsToSelector: @selector(canSendText)]) 244 | if ([NSClassFromString(@"MFMessageComposeViewController") performSelector: @selector(canSendText)]) 245 | return YES ; 246 | return NO ; 247 | } 248 | 249 | 250 | 251 | #pragma mark - 252 | #pragma mark Audio capabilities checking 253 | 254 | + (BOOL)isInSilentMode 255 | { 256 | /* 257 | NOTE: this won't work in the simulator, so we simply assume 258 | the simulator is never in silent mode 259 | */ 260 | if ([self isSimulator]) 261 | return NO ; 262 | else 263 | { 264 | // we first check if the AudioToolbox has been correctly imported 265 | #ifdef __AudioServices_h__ 266 | CFStringRef state ; 267 | UInt32 propertySize = sizeof(CFStringRef) ; 268 | AudioSessionInitialize(NULL, NULL, NULL, NULL) ; 269 | AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state) ; 270 | 271 | if(CFStringGetLength(state) == 0) 272 | return YES ; 273 | else 274 | return NO ; 275 | #else 276 | NSLog(@"import the AudioToolbox if you want to test that!") ; 277 | #endif 278 | } 279 | return NO ; 280 | } 281 | 282 | + (BOOL)hasSpeakersOn 283 | { 284 | /* 285 | NOTE: this won't work in the simulator, so we simply assume 286 | the simulator always has speakers on 287 | */ 288 | if ([self isSimulator]) 289 | return NO ; 290 | else 291 | { 292 | // we first check if the AudioToolbox has been correctly imported 293 | #ifdef __AudioServices_h__ 294 | CFStringRef state ; 295 | UInt32 propertySize = sizeof(CFStringRef) ; 296 | AudioSessionInitialize(NULL, NULL, NULL, NULL) ; 297 | AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state) ; 298 | if (CFStringGetLength(state) == 0) 299 | return NO ; 300 | else 301 | if ([(NSString *)state isEqualToString: @"Speaker"]) 302 | return YES ; 303 | #else 304 | NSLog(@"import the AudioToolbox if you want to test that!") ; 305 | #endif 306 | } 307 | return NO ; 308 | } 309 | 310 | + (BOOL)hasHeadphonesPlugged 311 | { 312 | /* 313 | NOTE: this won't work in the simulator, so we simply assume 314 | the simulator never has headphones plugged in 315 | */ 316 | if ([self isSimulator]) 317 | return NO ; 318 | else 319 | { 320 | // we first check if the AudioToolbox has been correctly imported 321 | #ifdef __AudioServices_h__ 322 | CFStringRef state ; 323 | UInt32 propertySize = sizeof(CFStringRef) ; 324 | AudioSessionInitialize(NULL, NULL, NULL, NULL) ; 325 | AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &state) ; 326 | if (CFStringGetLength(state) == 0) 327 | return NO ; 328 | else 329 | if ([(NSString *)state isEqualToString: @"Headphone"]) 330 | return YES ; 331 | #else 332 | NSLog(@"import the AudioToolbox if you want to test that!") ; 333 | #endif 334 | } 335 | return NO ; 336 | } 337 | 338 | 339 | 340 | #pragma mark - 341 | #pragma mark Detect hardware capabilities 342 | 343 | + (BOOL)hasRetinaDisplay 344 | { 345 | if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f) 346 | return YES ; 347 | return NO ; 348 | } 349 | 350 | + (BOOL)hasCamera 351 | { 352 | if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) 353 | return YES ; 354 | return NO ; 355 | } 356 | 357 | + (BOOL)canRecordVideo 358 | { 359 | if ([UIImagePickerController respondsToSelector: @selector(availableMediaTypesForSourceType:)]) 360 | { 361 | NSArray *mediaType = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeCamera] ; 362 | if ([mediaType containsObject: kUTTypeMovie]) 363 | return YES ; 364 | } 365 | return NO ; 366 | } 367 | 368 | + (BOOL)hasFrontFacingCamera 369 | { 370 | if ([UIImagePickerController respondsToSelector: @selector(isCameraDeviceAvailable:)]) 371 | if ([UIImagePickerController performSelector: @selector(isCameraDeviceAvailable:) withObject: (id)UIImagePickerControllerCameraDeviceFront]) 372 | return YES ; 373 | return NO ; 374 | } 375 | 376 | + (BOOL)hasRearFlashLight 377 | { 378 | if ([UIImagePickerController respondsToSelector: @selector(isFlashAvailableForCameraDevice:)]) 379 | if ([UIImagePickerController performSelector: @selector(isFlashAvailableForCameraDevice:) withObject: (id)UIImagePickerControllerCameraDeviceRear]) 380 | return YES ; 381 | return NO ; 382 | } 383 | 384 | + (BOOL)hasCompass 385 | { 386 | if ([NSClassFromString(@"CLLocationManager") respondsToSelector: @selector(headingAvailable)]) 387 | { 388 | // in iOS 4.0, headingAvailable is a class method 389 | if ([NSClassFromString(@"CLLocationManager") performSelector: @selector(headingAvailable)]) 390 | return YES ; 391 | } 392 | else 393 | { 394 | // prior to iOS 4.0, headingAvailable is a property (deprecated in iOS 4.0) 395 | id coreLocationManager = [[[NSClassFromString(@"CLLocationManager") alloc] init] autorelease] ; 396 | if ([coreLocationManager respondsToSelector: @selector(headingAvailable)]) 397 | return YES ; 398 | } 399 | return NO ; 400 | } 401 | 402 | + (BOOL)hasGyroscope 403 | { 404 | // we first check whether the CoreMotion manager class is defined 405 | if (NSClassFromString(@"CMMotionManager") == nil) 406 | return NO ; 407 | // if it is defined (iOS >= 4.0), we check if the device has the gyroscope 408 | id coreMotionManager = [[[NSClassFromString(@"CMMotionManager") alloc] init] autorelease] ; 409 | if ([coreMotionManager performSelector: @selector(isGyroAvailable)]) 410 | return YES ; 411 | return NO ; 412 | } 413 | 414 | @end 415 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | * Copyright (c) 2010-2011, Snappy Code 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Snappy Code nor the 12 | * names of its contributors may be used to endorse or promote products 13 | * derived from this software without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Snappy Code ''AS IS'' AND ANY 16 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL Snappy Code BE LIABLE FOR ANY 19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The DDDeviceDetection class provides handy class methods to check the hardware/software capabilities of your iOS device. --------------------------------------------------------------------------------