YYKit源码探究(二十六) —— UIDevice分类框架及Device Information(一)

版本记录

版本号 时间
V1.0 2018.03.28

前言

iOS圈内有几个人大家基本都知道,比如说王巍、唐巧,还有YYKit框架的作者现任职于滴滴的郭曜源 - ibireme等。这里有一篇唐巧对他的专访,还有他的 GitHub - Yaoyuan博客,这里贴出来框架YYKit 框架。接下来几篇我们就一起来看一下这个框架。感兴趣的可以看上面写的几篇。
1. YYKit源码探究(一) —— 基本概览
2. YYKit源码探究(二) —— NSString分类之Hash(一)
3. YYKit源码探究(三) —— NSString分类之Encode and decode(二)
4. YYKit源码探究(四) —— NSString分类之Drawing(三)
5. YYKit源码探究(五) —— NSString分类之Regular Expression(四)
6. YYKit源码探究(六) —— NSString分类之NSNumber Compatible(五)
7. YYKit源码探究(七) —— NSString分类之Utilities(六)
8. YYKit源码探究(八) —— NSNumber分类(一)
9. YYKit源码探究(九) —— UIFont分类之架构分析和Font Traits(一)
10. YYKit源码探究(十) —— UIFont分类之Create font(二)
11. YYKit源码探究(十一) —— UIFont分类之Load and unload font(三)
12. YYKit源码探究(十二) —— UIFont分类之Dump font data(四)
13. YYKit源码探究(十三) —— UIImage分类之框架结构和Create image部分(一)
14. YYKit源码探究(十四) —— UIImage分类之Image Info(二)
15. YYKit源码探究(十五) —— UIImage分类之Modify Image(三)
16. YYKit源码探究(十六) —— UIImage分类之Image Effect(四)
17. YYKit源码探究(十七) —— UIImageView分类之架构和image部分(一)
18. YYKit源码探究(十八) —— UIImageView分类之highlight image部分(二)
19. YYKit源码探究(十九) —— UIScreen分类(一)
20. YYKit源码探究(二十) —— UIScrollView分类(一)
21. YYKit源码探究(二十一) —— UITableView分类(一)
22. YYKit源码探究(二十二) —— UITextField分类(一)
23. YYKit源码探究(二十三) —— UIView分类(一)
24. YYKit源码探究(二十四) —— UIPasteboard分类(一)
25. YYKit源码探究(二十五) —— UIGestureRecognizer分类(一)

回顾

上一篇主要介绍了UIGestureRecognizer分类,这一篇主要看一下UIDevice部分。


框架结构

下面我们看一下UIDevice分类的框架。


Device Information - API

下面我们看一下API。

/// Device system version (e.g. 8.1)
+ (double)systemVersion;

/// Whether the device is iPad/iPad mini.
@property (nonatomic, readonly) BOOL isPad;

/// Whether the device is a simulator.
@property (nonatomic, readonly) BOOL isSimulator;

/// Whether the device is jailbroken.
@property (nonatomic, readonly) BOOL isJailbroken;

/// Wherher the device can make phone calls.
@property (nonatomic, readonly) BOOL canMakePhoneCalls NS_EXTENSION_UNAVAILABLE_IOS("");

/// The device's machine model.  e.g. "iPhone6,1" "iPad4,6"
/// @see http://theiphonewiki.com/wiki/Models
@property (nullable, nonatomic, readonly) NSString *machineModel;

/// The device's machine model name. e.g. "iPhone 5s" "iPad mini 2"
/// @see http://theiphonewiki.com/wiki/Models
@property (nullable, nonatomic, readonly) NSString *machineModelName;

/// The System's startup time.
@property (nonatomic, readonly) NSDate *systemUptime;

下面我们就详细的看一下这个API。

1. + (double)systemVersion;

该方法的作用就是返回系统的版本。

方法实现

+ (double)systemVersion {
    static double version;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        version = [UIDevice currentDevice].systemVersion.doubleValue;
    });
    return version;
}

2. @property (nonatomic, readonly) BOOL isPad;

判断设备是否是iPad和iPad mini。

方法实现

- (BOOL)isPad {
    static dispatch_once_t one;
    static BOOL pad;
    dispatch_once(&one, ^{
        pad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
    });
    return pad;
}

3. @property (nonatomic, readonly) BOOL isSimulator;

该属性的作用是判断设备是否是模拟器。

方法实现

- (BOOL)isSimulator {
#if TARGET_OS_SIMULATOR
    return YES;
#else
    return NO;
#endif
}

4. @property (nonatomic, readonly) BOOL isJailbroken;

判断设备是否是越狱机。

方法实现

- (BOOL)isJailbroken {
    if ([self isSimulator]) return NO; // Dont't check simulator
    
    // iOS9 URL Scheme query changed ...
    // NSURL *cydiaURL = [NSURL URLWithString:@"cydia://package"];
    // if ([[UIApplication sharedApplication] canOpenURL:cydiaURL]) return YES;
    
    NSArray *paths = @[@"/Applications/Cydia.app",
                       @"/private/var/lib/apt/",
                       @"/private/var/lib/cydia",
                       @"/private/var/stash"];
    for (NSString *path in paths) {
        if ([[NSFileManager defaultManager] fileExistsAtPath:path]) return YES;
    }
    
    FILE *bash = fopen("/bin/bash", "r");
    if (bash != NULL) {
        fclose(bash);
        return YES;
    }
    
    NSString *path = [NSString stringWithFormat:@"/private/%@", [NSString stringWithUUID]];
    if ([@"test" writeToFile : path atomically : YES encoding : NSUTF8StringEncoding error : NULL]) {
        [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
        return YES;
    }
    
    return NO;
}

5. @property (nonatomic, readonly) BOOL canMakePhoneCalls

该属性的作用就是判断是否可以打电话。

NS_EXTENSION_UNAVAILABLE_IOS("");

6. @property (nullable, nonatomic, readonly) NSString *machineModel;

该属性的作用就是用来判断机型,比如"iPhone6,1" "iPad4,6"

方法实现

- (NSString *)machineModel {
    static dispatch_once_t one;
    static NSString *model;
    dispatch_once(&one, ^{
        size_t size;
        sysctlbyname("hw.machine", NULL, &size, NULL, 0);
        char *machine = malloc(size);
        sysctlbyname("hw.machine", machine, &size, NULL, 0);
        model = [NSString stringWithUTF8String:machine];
        free(machine);
    });
    return model;
}

7. @property (nullable, nonatomic, readonly) NSString *machineModelName;

该属性的作用就是用来判断机型名称,比如"iPhone 5s" "iPad mini 2"

方法实现

- (NSString *)machineModelName {
    static dispatch_once_t one;
    static NSString *name;
    dispatch_once(&one, ^{
        NSString *model = [self machineModel];
        if (!model) return;
        NSDictionary *dic = @{
            @"Watch1,1" : @"Apple Watch 38mm",
            @"Watch1,2" : @"Apple Watch 42mm",
            @"Watch2,3" : @"Apple Watch Series 2 38mm",
            @"Watch2,4" : @"Apple Watch Series 2 42mm",
            @"Watch2,6" : @"Apple Watch Series 1 38mm",
            @"Watch1,7" : @"Apple Watch Series 1 42mm",
            
            @"iPod1,1" : @"iPod touch 1",
            @"iPod2,1" : @"iPod touch 2",
            @"iPod3,1" : @"iPod touch 3",
            @"iPod4,1" : @"iPod touch 4",
            @"iPod5,1" : @"iPod touch 5",
            @"iPod7,1" : @"iPod touch 6",
            
            @"iPhone1,1" : @"iPhone 1G",
            @"iPhone1,2" : @"iPhone 3G",
            @"iPhone2,1" : @"iPhone 3GS",
            @"iPhone3,1" : @"iPhone 4 (GSM)",
            @"iPhone3,2" : @"iPhone 4",
            @"iPhone3,3" : @"iPhone 4 (CDMA)",
            @"iPhone4,1" : @"iPhone 4S",
            @"iPhone5,1" : @"iPhone 5",
            @"iPhone5,2" : @"iPhone 5",
            @"iPhone5,3" : @"iPhone 5c",
            @"iPhone5,4" : @"iPhone 5c",
            @"iPhone6,1" : @"iPhone 5s",
            @"iPhone6,2" : @"iPhone 5s",
            @"iPhone7,1" : @"iPhone 6 Plus",
            @"iPhone7,2" : @"iPhone 6",
            @"iPhone8,1" : @"iPhone 6s",
            @"iPhone8,2" : @"iPhone 6s Plus",
            @"iPhone8,4" : @"iPhone SE",
            @"iPhone9,1" : @"iPhone 7",
            @"iPhone9,2" : @"iPhone 7 Plus",
            @"iPhone9,3" : @"iPhone 7",
            @"iPhone9,4" : @"iPhone 7 Plus",
            
            @"iPad1,1" : @"iPad 1",
            @"iPad2,1" : @"iPad 2 (WiFi)",
            @"iPad2,2" : @"iPad 2 (GSM)",
            @"iPad2,3" : @"iPad 2 (CDMA)",
            @"iPad2,4" : @"iPad 2",
            @"iPad2,5" : @"iPad mini 1",
            @"iPad2,6" : @"iPad mini 1",
            @"iPad2,7" : @"iPad mini 1",
            @"iPad3,1" : @"iPad 3 (WiFi)",
            @"iPad3,2" : @"iPad 3 (4G)",
            @"iPad3,3" : @"iPad 3 (4G)",
            @"iPad3,4" : @"iPad 4",
            @"iPad3,5" : @"iPad 4",
            @"iPad3,6" : @"iPad 4",
            @"iPad4,1" : @"iPad Air",
            @"iPad4,2" : @"iPad Air",
            @"iPad4,3" : @"iPad Air",
            @"iPad4,4" : @"iPad mini 2",
            @"iPad4,5" : @"iPad mini 2",
            @"iPad4,6" : @"iPad mini 2",
            @"iPad4,7" : @"iPad mini 3",
            @"iPad4,8" : @"iPad mini 3",
            @"iPad4,9" : @"iPad mini 3",
            @"iPad5,1" : @"iPad mini 4",
            @"iPad5,2" : @"iPad mini 4",
            @"iPad5,3" : @"iPad Air 2",
            @"iPad5,4" : @"iPad Air 2",
            @"iPad6,3" : @"iPad Pro (9.7 inch)",
            @"iPad6,4" : @"iPad Pro (9.7 inch)",
            @"iPad6,7" : @"iPad Pro (12.9 inch)",
            @"iPad6,8" : @"iPad Pro (12.9 inch)",
            
            @"AppleTV2,1" : @"Apple TV 2",
            @"AppleTV3,1" : @"Apple TV 3",
            @"AppleTV3,2" : @"Apple TV 3",
            @"AppleTV5,3" : @"Apple TV 4",
            
            @"i386" : @"Simulator x86",
            @"x86_64" : @"Simulator x64",
        };
        name = dic[model];
        if (!name) name = model;
    });
    return name;
}

8. @property (nonatomic, readonly) NSDate *systemUptime;

该属性的作用就是获取系统开始时间。

方法实现

- (NSDate *)systemUptime {
    NSTimeInterval time = [[NSProcessInfo processInfo] systemUptime];
    return [[NSDate alloc] initWithTimeIntervalSinceNow:(0 - time)];
}

后记

本篇主要介绍了UIDevice的分类架构以及Device Information部分,感兴趣的可以给个赞或者关注~~~

推荐阅读更多精彩内容