版本記錄
| 版本號(hào) | 時(shí)間 |
|---|---|
| V1.0 | 2018.03.30 |
前言
iOS圈內(nèi)有幾個(gè)人大家基本都知道,比如說王巍、唐巧,還有YYKit框架的作者現(xiàn)任職于滴滴的郭曜源 - ibireme等。這里有一篇唐巧對(duì)他的專訪,還有他的 GitHub - Yaoyuan 和 博客,這里貼出來框架YYKit 框架。接下來幾篇我們就一起來看一下這個(gè)框架。感興趣的可以看上面寫的幾篇。
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分類之架構(gòu)分析和Font Traits(一)
10. YYKit源碼探究(十) —— UIFont分類之Create font(二)
11. YYKit源碼探究(十一) —— UIFont分類之Load and unload font(三)
12. YYKit源碼探究(十二) —— UIFont分類之Dump font data(四)
13. YYKit源碼探究(十三) —— UIImage分類之框架結(jié)構(gòu)和Create image部分(一)
14. YYKit源碼探究(十四) —— UIImage分類之Image Info(二)
15. YYKit源碼探究(十五) —— UIImage分類之Modify Image(三)
16. YYKit源碼探究(十六) —— UIImage分類之Image Effect(四)
17. YYKit源碼探究(十七) —— UIImageView分類之架構(gòu)和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分類(一)
26. YYKit源碼探究(二十六) —— UIDevice分類框架及Device Information(一)
27. YYKit源碼探究(二十七) —— UIDevice分類之Network Information(二)
28. YYKit源碼探究(二十八) —— UIDevice分類之Disk Space(三)
29. YYKit源碼探究(二十九) —— UIDevice分類之Memory Information(四)
30. YYKit源碼探究(三十) —— UIDevice分類之CPU Information(五)
31. YYKit源碼探究(三十一) —— UIControl分類(一)
32. YYKit源碼探究(三十二) —— UIColor分類之Create a UIColor Object(一)
33. YYKit源碼探究(三十三) —— UIColor分類之Get color's description(二)
34. YYKit源碼探究(三十四) —— UIColor分類之Retrieving Color Information(三)
35. YYKit源碼探究(三十五) —— UIButton分類之image(一)
36. YYKit源碼探究(三十六) —— UIButton分類之background image(二)
37. YYKit源碼探究(三十七) —— UIBezierPath分類(一)
38. YYKit源碼探究(三十八) —— UIBarButtonItem分類(一)
回顧
上一篇主要介紹了UIBarButtonItem分類,這一篇主要看一下UIApplication分類。
API
下面我們一起來看一下API文檔。
/// "Documents" folder in this app's sandbox.
@property (nonatomic, readonly) NSURL *documentsURL;
@property (nonatomic, readonly) NSString *documentsPath;
/// "Caches" folder in this app's sandbox.
@property (nonatomic, readonly) NSURL *cachesURL;
@property (nonatomic, readonly) NSString *cachesPath;
/// "Library" folder in this app's sandbox.
@property (nonatomic, readonly) NSURL *libraryURL;
@property (nonatomic, readonly) NSString *libraryPath;
/// Application's Bundle Name (show in SpringBoard).
@property (nullable, nonatomic, readonly) NSString *appBundleName;
/// Application's Bundle ID. e.g. "com.ibireme.MyApp"
@property (nullable, nonatomic, readonly) NSString *appBundleID;
/// Application's Version. e.g. "1.2.0"
@property (nullable, nonatomic, readonly) NSString *appVersion;
/// Application's Build number. e.g. "123"
@property (nullable, nonatomic, readonly) NSString *appBuildVersion;
/// Whether this app is pirated (not install from appstore).
@property (nonatomic, readonly) BOOL isPirated;
/// Whether this app is being debugged (debugger attached).
@property (nonatomic, readonly) BOOL isBeingDebugged;
/// Current thread real memory used in byte. (-1 when error occurs)
@property (nonatomic, readonly) int64_t memoryUsage;
/// Current thread CPU usage, 1.0 means 100%. (-1 when error occurs)
@property (nonatomic, readonly) float cpuUsage;
/**
Increments the number of active network requests.
If this number was zero before incrementing, this will start animating the
status bar network activity indicator.
This method is thread safe.
This method has no effect in App Extension.
*/
- (void)incrementNetworkActivityCount;
/**
Decrements the number of active network requests.
If this number becomes zero after decrementing, this will stop animating the
status bar network activity indicator.
This method is thread safe.
This method has no effect in App Extension.
*/
- (void)decrementNetworkActivityCount;
/// Returns YES in App Extension.
+ (BOOL)isAppExtension;
/// Same as sharedApplication, but returns nil in App Extension.
+ (nullable UIApplication *)sharedExtensionApplication;
下面我們就詳細(xì)的看一下這個(gè)API
1. @property (nonatomic, readonly) NSURL *documentsURL;
這個(gè)屬性的作用就是獲取Documents的文件目錄。
方法實(shí)現(xiàn)
- (NSURL *)documentsURL {
return [[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
}
2. @property (nonatomic, readonly) NSString *documentsPath;
這個(gè)屬性的作用就是獲取Documents的文件目錄。
方法實(shí)現(xiàn)
- (NSString *)documentsPath {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
}
3. @property (nonatomic, readonly) NSURL *cachesURL;
這個(gè)屬性的作用就是獲取cache的文件目錄。
方法實(shí)現(xiàn)
- (NSURL *)cachesURL {
return [[[NSFileManager defaultManager]
URLsForDirectory:NSCachesDirectory
inDomains:NSUserDomainMask] lastObject];
}
4. @property (nonatomic, readonly) NSString *cachesPath;
這個(gè)屬性的作用就是獲取cache的文件目錄。
方法實(shí)現(xiàn)
- (NSString *)cachesPath {
return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
}
5. @property (nonatomic, readonly) NSURL *libraryURL;
這個(gè)屬性的作用就是獲取library的文件目錄。
方法實(shí)現(xiàn)
- (NSURL *)libraryURL {
return [[[NSFileManager defaultManager]
URLsForDirectory:NSLibraryDirectory
inDomains:NSUserDomainMask] lastObject];
}
6. @property (nonatomic, readonly) NSString *libraryPath;
這個(gè)屬性的作用就是獲取library的文件目錄。
方法實(shí)現(xiàn)
- (NSString *)libraryPath {
return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
}
7. @property (nullable, nonatomic, readonly) NSString *appBundleName;
這個(gè)屬性的作用就是獲取Application's Bundle Name。
方法實(shí)現(xiàn)
- (NSString *)appBundleName {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
}
8. @property (nullable, nonatomic, readonly) NSString *appBundleID;
這個(gè)屬性的作用就是獲取Application's Bundle ID。
方法實(shí)現(xiàn)
- (NSString *)appBundleID {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
}
9. @property (nullable, nonatomic, readonly) NSString *appVersion;
這個(gè)屬性的作用就是獲取Application's Version。
方法實(shí)現(xiàn)
- (NSString *)appVersion {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
}
10. @property (nullable, nonatomic, readonly) NSString *appBuildVersion;
這個(gè)屬性的作用就是獲取Application's Build number。
方法實(shí)現(xiàn)
- (NSString *)appBuildVersion {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
}
11. @property (nonatomic, readonly) BOOL isPirated;
這個(gè)屬性的作用就是判斷是否是盜版的,也就是不是從apple store中下載的。
方法實(shí)現(xiàn)
- (BOOL)isPirated {
if ([[UIDevice currentDevice] isSimulator]) return YES; // Simulator is not from appstore
if (getgid() <= 10) return YES; // process ID shouldn't be root
if ([[[NSBundle mainBundle] infoDictionary] objectForKey:@"SignerIdentity"]) {
return YES;
}
if (![self _yy_fileExistInMainBundle:@"_CodeSignature"]) {
return YES;
}
if (![self _yy_fileExistInMainBundle:@"SC_Info"]) {
return YES;
}
//if someone really want to crack your app, this method is useless..
//you may change this method's name, encrypt the code and do more check..
return NO;
}
- (BOOL)_yy_fileExistInMainBundle:(NSString *)name {
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *path = [NSString stringWithFormat:@"%@/%@", bundlePath, name];
return [[NSFileManager defaultManager] fileExistsAtPath:path];
}
12. @property (nonatomic, readonly) BOOL isBeingDebugged;
這個(gè)屬性的作用就是判斷是不是正在調(diào)試。
方法實(shí)現(xiàn)
- (BOOL)isBeingDebugged {
size_t size = sizeof(struct kinfo_proc);
struct kinfo_proc info;
int ret = 0, name[4];
memset(&info, 0, sizeof(struct kinfo_proc));
name[0] = CTL_KERN;
name[1] = KERN_PROC;
name[2] = KERN_PROC_PID; name[3] = getpid();
if (ret == (sysctl(name, 4, &info, &size, NULL, 0))) {
return ret != 0;
}
return (info.kp_proc.p_flag & P_TRACED) ? YES : NO;
}
13. @property (nonatomic, readonly) int64_t memoryUsage;
這個(gè)屬性的作用就是計(jì)算內(nèi)存的使用。
方法實(shí)現(xiàn)
- (int64_t)memoryUsage {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kern = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
if (kern != KERN_SUCCESS) return -1;
return info.resident_size;
}
14. @property (nonatomic, readonly) float cpuUsage;
這個(gè)屬性的作用就是計(jì)算當(dāng)前CPU的使用。
方法實(shí)現(xiàn)
- (float)cpuUsage {
kern_return_t kr;
task_info_data_t tinfo;
mach_msg_type_number_t task_info_count;
task_info_count = TASK_INFO_MAX;
kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
if (kr != KERN_SUCCESS) {
return -1;
}
thread_array_t thread_list;
mach_msg_type_number_t thread_count;
thread_info_data_t thinfo;
mach_msg_type_number_t thread_info_count;
thread_basic_info_t basic_info_th;
kr = task_threads(mach_task_self(), &thread_list, &thread_count);
if (kr != KERN_SUCCESS) {
return -1;
}
long tot_sec = 0;
long tot_usec = 0;
float tot_cpu = 0;
int j;
for (j = 0; j < thread_count; j++) {
thread_info_count = THREAD_INFO_MAX;
kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
(thread_info_t)thinfo, &thread_info_count);
if (kr != KERN_SUCCESS) {
return -1;
}
basic_info_th = (thread_basic_info_t)thinfo;
if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE;
}
}
kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
assert(kr == KERN_SUCCESS);
return tot_cpu;
}
15. - (void)incrementNetworkActivityCount;
增加活動(dòng)網(wǎng)絡(luò)請(qǐng)求的數(shù)量。 如果此數(shù)字在增量之前為零,則會(huì)啟動(dòng)狀態(tài)欄網(wǎng)絡(luò)活動(dòng)指示器的動(dòng)畫。這個(gè)方法是線程安全的,并且對(duì)App Extension沒有影響。
方法實(shí)現(xiàn)
- (void)incrementNetworkActivityCount {
[self _changeNetworkActivityCount:1];
}
- (void)_changeNetworkActivityCount:(NSInteger)delta {
@synchronized(self){
dispatch_async_on_main_queue(^{
_YYUIApplicationNetworkIndicatorInfo *info = [self networkActivityInfo];
if (!info) {
info = [_YYUIApplicationNetworkIndicatorInfo new];
[self setNetworkActivityInfo:info];
}
NSInteger count = info.count;
count += delta;
info.count = count;
[info.timer invalidate];
info.timer = [NSTimer timerWithTimeInterval:kNetworkIndicatorDelay target:self selector:@selector(_delaySetActivity:) userInfo:@(info.count > 0) repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:info.timer forMode:NSRunLoopCommonModes];
});
}
}
16. - (void)decrementNetworkActivityCount;
減少活動(dòng)網(wǎng)絡(luò)請(qǐng)求的數(shù)量。 如果此數(shù)字在遞減后變?yōu)榱?,則會(huì)停止為狀態(tài)欄網(wǎng)絡(luò)活動(dòng)指示器設(shè)置動(dòng)畫。這個(gè)方法是線程安全的,并且對(duì)App Extension沒有影響。
方法實(shí)現(xiàn)
- (void)decrementNetworkActivityCount {
[self _changeNetworkActivityCount:-1];
}
17. + (BOOL)isAppExtension;
如果是AppExtension就返回YES。
方法實(shí)現(xiàn)
+ (BOOL)isAppExtension {
static BOOL isAppExtension = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class cls = NSClassFromString(@"UIApplication");
if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES;
if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES;
});
return isAppExtension;
}
18. + (nullable UIApplication *)sharedExtensionApplication;
與sharedApplication相同,但在App Extension中返回nil。
方法實(shí)現(xiàn)
+ (UIApplication *)sharedExtensionApplication {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
return [self isAppExtension] ? nil : [UIApplication performSelector:@selector(sharedApplication)];
#pragma clang diagnostic pop
}
后記
本篇講述了
UIApplication的分類,感興趣的可以給個(gè)贊或者關(guān)注~~~
